Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FileSystemHandle.move method #10

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
255 changes: 255 additions & 0 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,9 @@ interface FileSystemHandle {
readonly attribute USVString name;

Promise<boolean> isSameEntry(FileSystemHandle other);
Promise<undefined> move(USVString newEntryName);
Promise<undefined> move(FileSystemDirectoryHandle destinationDirectory);
Promise<undefined> move(FileSystemDirectoryHandle destinationDirectory, USVString newEntryName);
};
</xmp>

Expand Down Expand Up @@ -416,6 +419,258 @@ The <dfn method for=FileSystemHandle>isSameEntry(|other|)</dfn> method steps are

</div>

### The {{FileSystemHandle/move(destinationDirectory, newEntryName)|move()}} method ### {#api-filesystemhandle-move}

<div class="note domintro">
: await |handle| . {{FileSystemHandle/move(newEntryName)|move}}({ {{USVString}}: |newEntryName|})
:: Renames the [=file system entry=] [=locate an entry|locatable=] by
|handle|'s [=FileSystemHandle/locator=] to |newEntryName|.

: await |handle| . {{FileSystemHandle/move(destinationDirectory)|move}}({ {{FileSystemDirectoryHandle}}: |destinationDirectory|})
:: Moves the [=file system entry=] [=locate an entry|locatable=] by
|handle|'s [=FileSystemHandle/locator=] to the [=directory entry=]
[=locate an entry|locatable=] by |destinationDirectory|'s
[=FileSystemHandle/locator=], while keeping its existing name.

: await |handle| . {{FileSystemHandle/move(destinationDirectory, newEntryName)|move}}({ {{FileSystemDirectoryHandle}}: |destinationDirectory|, {{USVString}}: |newEntryName|})
:: Moves the [=file system entry=] [=locate an entry|locatable=] by
|handle|'s [=FileSystemHandle/locator=] to the [=directory entry=]
[=locate an entry|locatable=] by |destinationDirectory|'s
[=FileSystemHandle/locator=], as well as renaming to |newEntryName|.

If the [=file system locator/root|roots=] of the respective
[=FileSystemHandle/locator|locators=] of |destinationDirectory| and
|handle| are not the same, this operation may abort or fail non-atomically.
</div>

<div algorithm>
The <dfn method for=FileSystemHandle>move({{FileSystemDirectoryHandle}}: |destinationDirectory|)</dfn>
method steps are to [=FileSystemHandle/move=] [=this=]
given [=this=]'s {{FileSystemHandle/name}} and |destinationDirectory|.

</div>

<div algorithm>
The <dfn method for=FileSystemHandle>move({{USVString}}: |newEntryName|)</dfn>
method steps are to [=FileSystemHandle/move=] [=this=]
given |newEntryName|.

</div>

<div algorithm>
The <dfn method for=FileSystemHandle>move({{FileSystemDirectoryHandle}}: |destinationDirectory|, {{USVString}}: |newEntryName|)</dfn>
method steps are to [=FileSystemHandle/move=] [=this=]
given |newEntryName| and |destinationDirectory|.

</div>

<div algorithm>

To <dfn for=FileSystemHandle>move</dfn> a {{FileSystemHandle}} |handle| given
a {{USVString}} |newEntryName| and
an optional {{FileSystemDirectoryHandle}} |destinationDirectory|:

1. Let |result| be [=a new promise=].
1. Let |locator| be |handle|'s [=FileSystemHandle/locator=].
1. Let |global| be |handle|'s [=relevant global object=].
1. Let |isInABucketFileSystem| be true if
|handle| [=FileSystemHandle/is in a bucket file system=];
otherwise false.
1. [=Enqueue the following steps=] to the [=file system queue=]:
1. If |newEntryName| is not a [=valid file name=],
[=queue a storage task=] with |global| to [=/reject=] |result|
with a {{TypeError}} and abort these steps.

1. Let |entry| be the result of [=locating an entry=] given |locator|.
1. Let |accessResult| be the result of running |entry|'s
[=file system entry/request access=] given "`readwrite`".
1. If |accessResult|'s [=file system access result/permission state=]
is not "{{PermissionState/granted}}", [=queue a storage task=] with
|global| to [=/reject=] |result| with a {{DOMException}} of
|accessResult|'s [=file system access result/error name=] and
abort these steps.

1. If |destinationDirectory| was given:
1. Let |destinationDirectoryLocator| be
|destinationDirectory|'s [=FileSystemHandle/locator=].
1. Let |destinationDirectoryEntry| be the result of [=locating an entry=]
given |destinationDirectoryLocator|.

1. Let |destinationDirectoryAccessResult| be the result of running
|destinationDirectoryEntry|'s
[=file system entry/request access=] given "`readwrite`".
1. If |destinationDirectoryAccessResult|'s
[=file system access result/permission state=]
is not "{{PermissionState/granted}}", [=queue a storage task=] with
|global| to [=/reject=] |result| with a {{DOMException}} of
|accessResult|'s [=file system access result/error name=] and
abort these steps.

1. If |destinationDirectoryLocator|'s [=file system locator/root=] is not
|locator|'s [=file system locator/root=], [=queue a storage task=] with
|global| to [=/reject=] |result| with an
"{{NotSupportedError}}" {{DOMException}} and abort these steps.

Issue(114): Decide which moves across file systems, if any, should be
supported, or if this should be left up to individual user-agent
implementations.

1. Let |destinationPath| be the result of [=list/clone|cloning=]
|destinationDirectoryLocator|'s [=file system locator/path=] and
[=list/append|appending=] |newEntryName|.
1. Otherwise:
1. Let |destinationPath| be the result of [=list/clone|cloning=]
|locator|'s [=file system locator/path=], [=list/remove|removing=]
the last [=list/item=], and [=list/append|appending=] |newEntryName|.

1. Let |destinationLocator| be a [=/file system locator=] whose
[=file system locator/kind=] is |locator|'s [=file system locator/kind=],
[=file system locator/root=] is |locator|'s [=file system locator/root=], and
[=file system locator/path=] is |destinationPath|.
1. If the result of [=file system locator/resolving=] |destinationLocator|
relative to |locator| is not null and is not [=list/is empty|empty=],
[=queue a storage task=] with |global| to [=/reject=] |result| with a
"{{InvalidModificationError}}" {{DOMException}} and abort these steps.

Note: This prevents moving a directory within itself.

1. Let |destinationEntry| be the result of [=locating an entry=]
given |destinationLocator|.

1. If |destinationDirectory| was not given and
|destinationLocator| is not [=the same entry as=] |locator|:
1. Let |destinationAccessResult| be the result of running
|destinationEntry|'s [=file system entry/request access=]
given "`readwrite`".

Issue(101): Make sure this still makes sense once access check algorithms
are no longer associated with an entry.
1. Otherwise:
1. Let |destinationAccessResult| be |destinationDirectoryAccessResult|.

1. Let |isTheRootOfABucketFileSystem| be true if
|isInABucketFileSystem| is true and
|entry|'s [=file system entry/parent=] is `null`;
otherwise false.
1. If |isTheRootOfABucketFileSystem| is true,
[=queue a storage task=] with |global| to [=/reject=] |result| with a
"{{InvalidModificationError}}" {{DOMException}} and abort these steps.

Issue: Do not allow |entry| to be moved if it is a
<a href=https://wicg.github.io/file-system-access/#enumdef-wellknowndirectory>well-known directory</a>.

1. If |destinationAccessResult|'s
[=file system access result/permission state=] is not
"{{PermissionState/granted}}":
1. If |destinationEntry| is not `null`, [=queue a storage task=] with
|global| to [=/reject=] |result| with a {{DOMException}} of
|destinationAccessResult|'s [=file system access result/error name=] and
abort these steps

Note: This prevents overwriting an existing file or directory which the
website does not have access to. To prevent overwriting a file which
the site can access, use of the
<a href=https://www.w3.org/TR/web-locks/>Web Locks API</a> is encouraged.

Issue(46): Make it easier to generate a uniquely-identifying string for
a {{FileSystemHandle}}.

1. Let |settingsGlobal| be |handle|'s [=relevant settings object=]'s
[=environment settings object/global object=].
1. If |settingsGlobal| does not have [=transient activation=],
[=queue a storage task=] with |global| to [=/reject=] |result|
with a "{{NotAllowedError}}" {{DOMException}}.

1. If |entry| is `null`, [=queue a storage task=] with |global| to [=/reject=]
|result| with a "{{NotFoundError}}" {{DOMException}} and abort these steps.
1. If |destinationDirectory| was given and |destinationDirectoryEntry|
is `null`, [=queue a storage task=] with |global| to [=/reject=] |result|
with a "{{NotFoundError}}" {{DOMException}} and abort these steps.

1. Let |lockResult| be the result of [=file entry/lock/take|taking a lock=]
with "`exclusive`" on |entry|.

Issue(137): Support locking directory entries.

1. If |destinationEntry| is not `null`:
1. Let |destinationLockResult| be the result of
[=file entry/lock/take|taking a lock=] with "`exclusive`"
on |destinationEntry|.
1. Otherwise:
1. Let |destinationLockResult| be "`not taken`".

Issue: Consider whether it should be possible to lock a
[=/file system entry=] which does not (yet) exist.

1. [=Queue a storage task=] with |global| to run these steps:
1. If |lockResult| is "`failure`", [=/reject=] |result| with a
"{{NoModificationAllowedError}}" {{DOMException}} and abort these steps.
1. If |destinationLockResult| is "`failure`", [=/reject=] |result| with a
"{{NoModificationAllowedError}}" {{DOMException}} and abort these steps.

1. If |destinationLocator| is [=the same entry as=] |locator|,
[=enqueue the following steps=] to the [=file system queue=]:
1. [=file entry/lock/release|Release the lock=] on |entry|.
1. [=Queue a storage task=] with |global| to
[=/resolve=] |result| with `undefined` and abort these steps.

1. If |entry| is a [=file entry=] and |isInABucketFileSystem| is false,
run [=implementation-defined=] malware scans and safe browsing checks.
If these checks fail, [=/reject=] |result| with an
"{{AbortError}}" {{DOMException}} and abort these steps.

1. Let |sourceQueryAccess| be |entry|'s [=file system entry/query access=].
1. Let |sourceRequestAccess| be |entry|'s [=file system entry/request access=].

1. If |destinationDirectory| was given:
1. [=set/Append=] |entry| to |destinationDirectoryEntry|'s
[=directory entry/children=].

1. Attempt to move |entry| to |destinationEntry| in the underlying file
system. If that throws an exception, [=/reject=] |result| with that
exception and abort these steps.

Note: In some cases, moving a file or directory can fail non-atomically.
A file move may result in a partially-written |destinationEntry|.
A directory move may result in only some files or sub-folders being
copied to |destinationEntry|, and some containing files may themselves
fail to be moved atomically.
In both cases, |entry| will only be removed from the underlying file
system if all contents were successfully moved to |destinationEntry|.

1. If |destinationDirectory| was given:
1. If |entry|'s [=file system entry/parent=] is not `null`,
[=set/remove=] |entry| from |entry|'s [=file system entry/parent=]'s
[=directory entry/children=].

1. Set |handle|'s [=FileSystemHandle/locator=] to |destinationLocator|.

Note: This does not update other {{FileSystemHandle}}s with the same
[=FileSystemHandle/locator=], nor does it update any {{FileSystemHandle}}
which [=locate an entry|located to=] any of |handle|'s
[=directory entry/children=] if |handle| is a [=directory entry=].
Each of these handles will presumably no longer [=locate an entry=],
unless a new entry is created at the respective location.

1. Set |destinationEntry|'s [=file system entry/query access=] to
|sourceQueryAccess|.
1. Set |destinationEntry|'s [=file system entry/request access=] to
|sourceRequestAccess|.

Issue(101): Make sure this still makes sense once access check
algorithms are no longer associated with an entry.

1. [=Enqueue the following steps=] to the [=file system queue=]:
1. [=file entry/lock/release|Release the lock=] on |entry|.
1. If |destinationLockResult| is "`success`",
[=file entry/lock/release|release the lock=] on |destinationEntry|.
1. [=Queue a storage task=] with |global| to
[=/resolve=] |result| with `undefined`.

1. Return |result|.

</div>

## The {{FileSystemFileHandle}} interface ## {#api-filesystemfilehandle}

<xmp class=idl>
Expand Down