From aae8af4b80d0007230e3692cdcf9d71b0abe01cc Mon Sep 17 00:00:00 2001 From: Austin Sullivan Date: Sun, 16 Jul 2023 21:13:27 -0400 Subject: [PATCH 01/12] revamp move --- index.bs | 201 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) diff --git a/index.bs b/index.bs index 267287d..20e96a9 100644 --- a/index.bs +++ b/index.bs @@ -335,6 +335,9 @@ interface FileSystemHandle { readonly attribute USVString name; Promise isSameEntry(FileSystemHandle other); + Promise move(USVString newEntryName); + Promise move(FileSystemDirectoryHandle destinationDirectory); + Promise move(FileSystemDirectoryHandle destinationDirectory, USVString newEntryName); }; @@ -419,6 +422,204 @@ The isSameEntry(|other|) method steps are +### The {{FileSystemHandle/move(destinationDirectory, newEntryName)|move()}} method ### {#api-filesystemhandle-move} + +
+ : 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. +
+ +
+The move({{FileSystemDirectoryHandle}}: |destinationDirectory|) +method steps are to [=FileSystemHandle/move=] |handle| +given |handle|'s {{FileSystemHandle/name}} and |destinationDirectory|. + +
+ +
+The move({{USVString}}: |newEntryName|) +method steps are to [=FileSystemHandle/move=] |handle| +given |newEntryName|. + +
+ +
+The move({{FileSystemDirectoryHandle}}: |destinationDirectory|, {{USVString}}: |newEntryName|) +method steps are to [=FileSystemHandle/move=] |handle| +given |newEntryName| and |destinationDirectory|. + +
+ +
+ +To move 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. Let |destinationEntry| be the result of [=locating an entry=] + given |destinationLocator|. + + 1. If |destinationDirectory| was not given: + 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 + sensitive directory + + 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 + site does not have access to. + + 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 |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/Append=] |entry| to |destinationDirectoryEntry|'s + [=directory entry/children=]. + + 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. 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. + + 1. [=/Resolve=] |result| with `undefined`. + +1. Return |result|. + +
+ ## The {{FileSystemFileHandle}} interface ## {#api-filesystemfilehandle} From 0dd1c79d59ab9fa107810c33ce7abb66b64c0bb1 Mon Sep 17 00:00:00 2001 From: Austin Sullivan <asully@chromium.org> Date: Sun, 16 Jul 2023 21:19:07 -0400 Subject: [PATCH 02/12] release lock after move --- index.bs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/index.bs b/index.bs index 20e96a9..7964ec9 100644 --- a/index.bs +++ b/index.bs @@ -614,7 +614,10 @@ an optional {{FileSystemDirectoryHandle}} |destinationDirectory|: system. If that throws an exception, [=/reject=] |result| with that exception and abort these steps. - 1. [=/Resolve=] |result| with `undefined`. + 1. [=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`. 1. Return |result|. From f312106d1379298a294fb00dafb2d4c4aa7c937d Mon Sep 17 00:00:00 2001 From: Austin Sullivan <asully@chromium.org> Date: Sun, 16 Jul 2023 21:25:11 -0400 Subject: [PATCH 03/12] release lock on destination, too --- index.bs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/index.bs b/index.bs index 7964ec9..7d14f7d 100644 --- a/index.bs +++ b/index.bs @@ -614,8 +614,12 @@ an optional {{FileSystemDirectoryHandle}} |destinationDirectory|: 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. + 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`. From d706145426f374913e3b1a712ba7a04b9351b587 Mon Sep 17 00:00:00 2001 From: Austin Sullivan <asully@chromium.org> Date: Sun, 16 Jul 2023 22:30:19 -0400 Subject: [PATCH 04/12] expand notes + set locator to dest --- index.bs | 51 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/index.bs b/index.bs index 7d14f7d..048e12d 100644 --- a/index.bs +++ b/index.bs @@ -552,7 +552,7 @@ an optional {{FileSystemDirectoryHandle}} |destinationDirectory|: "{{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/#wellknowndirectory-too-sensitive-or-dangerous>sensitive directory</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 @@ -563,7 +563,12 @@ an optional {{FileSystemDirectoryHandle}} |destinationDirectory|: abort these steps Note: This prevents overwriting an existing file or directory which the - site does not have access to. + 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=]. @@ -598,23 +603,51 @@ an optional {{FileSystemDirectoryHandle}} |destinationDirectory|: 1. If |destinationLockResult| is "`failure`", [=/reject=] |result| with a "{{NoModificationAllowedError}}" {{DOMException}} and abort these steps. - 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/Append=] |entry| to |destinationDirectoryEntry|'s - [=directory entry/children=]. - 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|. From f00374645ecc5fe6a8749bb59bf8b6ee5a249041 Mon Sep 17 00:00:00 2001 From: Austin Sullivan <asully@chromium.org> Date: Sun, 16 Jul 2023 22:55:51 -0400 Subject: [PATCH 05/12] handle self-move --- index.bs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/index.bs b/index.bs index 048e12d..5950518 100644 --- a/index.bs +++ b/index.bs @@ -530,10 +530,18 @@ an optional {{FileSystemDirectoryHandle}} |destinationDirectory|: [=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: + 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`". @@ -603,6 +611,12 @@ an optional {{FileSystemDirectoryHandle}} |destinationDirectory|: 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`. + 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 From 3213227c57ffa1bef325036e7fd5e7e9173ca505 Mon Sep 17 00:00:00 2001 From: Austin Sullivan <asully@chromium.org> Date: Sun, 16 Jul 2023 23:20:22 -0400 Subject: [PATCH 06/12] exit early during self-move --- index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.bs b/index.bs index 5950518..5c636dc 100644 --- a/index.bs +++ b/index.bs @@ -615,7 +615,7 @@ an optional {{FileSystemDirectoryHandle}} |destinationDirectory|: [=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`. + [=/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. From 414622c24a4c87820c4527ffe86c71454d7a6626 Mon Sep 17 00:00:00 2001 From: Austin Sullivan <asully@chromium.org> Date: Mon, 17 Jul 2023 23:40:01 -0400 Subject: [PATCH 07/12] fix bs error --- index.bs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.bs b/index.bs index 5c636dc..0f14555 100644 --- a/index.bs +++ b/index.bs @@ -448,21 +448,21 @@ The <dfn method for=FileSystemHandle>isSameEntry(|other|)</dfn> method steps are <div algorithm> The <dfn method for=FileSystemHandle>move({{FileSystemDirectoryHandle}}: |destinationDirectory|)</dfn> -method steps are to [=FileSystemHandle/move=] |handle| -given |handle|'s {{FileSystemHandle/name}} and |destinationDirectory|. +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=] |handle| +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=] |handle| +method steps are to [=FileSystemHandle/move=] [=this=] given |newEntryName| and |destinationDirectory|. </div> From eaf6b439f885b0e656e1b5981ddbf3e8b58d4d80 Mon Sep 17 00:00:00 2001 From: valadaptive <valadaptive@protonmail.com> Date: Sun, 4 Jan 2026 08:20:47 -0500 Subject: [PATCH 08/12] Move the `move` method and reword --- index.bs | 95 ++++++++++++++++++++++++-------------------------------- 1 file changed, 40 insertions(+), 55 deletions(-) diff --git a/index.bs b/index.bs index 0f14555..c843602 100644 --- a/index.bs +++ b/index.bs @@ -335,9 +335,6 @@ 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); }; @@ -422,56 +419,62 @@ The isSameEntry(|other|) method steps are -### The {{FileSystemHandle/move(destinationDirectory, newEntryName)|move()}} method ### {#api-filesystemhandle-move} +### The {{FileSystemFileHandle/move(destinationDirectory, newEntryName)|move()}} method ### {#api-filesystemhandle-move}
- : await |handle| . {{FileSystemHandle/move(newEntryName)|move}}({ {{USVString}}: |newEntryName|}) + : await fileHhandle| . {{FileSystemFileHandle/move(newEntryName)|move}}({ {{USVString}}: |newEntryName|}) :: Renames the [=file system entry=] [=locate an entry|locatable=] by - |handle|'s [=FileSystemHandle/locator=] to |newEntryName|. + |fileHandle|'s [=FileSystemHandle/locator=] to |newEntryName|. - : await |handle| . {{FileSystemHandle/move(destinationDirectory)|move}}({ {{FileSystemDirectoryHandle}}: |destinationDirectory|}) + : await |fileHandle| . {{FileSystemFileHandle/move(destinationDirectory)|move}}({ {{FileSystemDirectoryHandle}}: |destinationDirectory|}) :: Moves the [=file system entry=] [=locate an entry|locatable=] by - |handle|'s [=FileSystemHandle/locator=] to the [=directory entry=] + |fileHandle|'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|}) + If the [=file system locator/root|roots=] of the respective + [=FileSystemHandle/locator|locators=] of |destinationDirectory| and + |fileHandle| are not the same, this operation might abort or fail + non-atomically. + + : await |fileHandle| . {{FileSystemFileHandle/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=] + |fileHandle|'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. + |fileHandle| are not the same, this operation might abort or fail + non-atomically.
-The move({{FileSystemDirectoryHandle}}: |destinationDirectory|) -method steps are to [=FileSystemHandle/move=] [=this=] +The move({{FileSystemDirectoryHandle}}: |destinationDirectory|) +method steps are to [=FileSystemFileHandle/move=] [=this=] given [=this=]'s {{FileSystemHandle/name}} and |destinationDirectory|.
-The move({{USVString}}: |newEntryName|) -method steps are to [=FileSystemHandle/move=] [=this=] +The move({{USVString}}: |newEntryName|) +method steps are to [=FileSystemFileHandle/move=] [=this=] given |newEntryName|.
-The move({{FileSystemDirectoryHandle}}: |destinationDirectory|, {{USVString}}: |newEntryName|) -method steps are to [=FileSystemHandle/move=] [=this=] +The move({{FileSystemDirectoryHandle}}: |destinationDirectory|, {{USVString}}: |newEntryName|) +method steps are to [=FileSystemFileHandle/move=] [=this=] given |newEntryName| and |destinationDirectory|.
-To move a {{FileSystemHandle}} |handle| given -a {{USVString}} |newEntryName| and -an optional {{FileSystemDirectoryHandle}} |destinationDirectory|: +To move a {{FileSystemFileHandle}} |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=]. @@ -530,12 +533,6 @@ an optional {{FileSystemDirectoryHandle}} |destinationDirectory|: [=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|. @@ -551,24 +548,13 @@ an optional {{FileSystemDirectoryHandle}} |destinationDirectory|: 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 - well-known directory. - 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 + 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 @@ -593,8 +579,6 @@ an optional {{FileSystemDirectoryHandle}} |destinationDirectory|: 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`" @@ -617,10 +601,9 @@ an optional {{FileSystemDirectoryHandle}} |destinationDirectory|: 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. If |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=]. @@ -634,12 +617,12 @@ an optional {{FileSystemDirectoryHandle}} |destinationDirectory|: 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|. + A file move might result in a partially-written |destinationEntry|. + A directory move might result in only some files or sub-folders being + copied to |destinationEntry|, and some containing files might 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`, @@ -649,11 +632,9 @@ an optional {{FileSystemDirectoryHandle}} |destinationDirectory|: 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. + [=FileSystemHandle/locator=]. 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|. @@ -687,6 +668,10 @@ interface FileSystemFileHandle : FileSystemHandle { Promise createWritable(optional FileSystemCreateWritableOptions options = {}); [Exposed=DedicatedWorker] Promise createSyncAccessHandle(); + + Promise move(USVString newEntryName); + Promise move(FileSystemDirectoryHandle destinationDirectory); + Promise move(FileSystemDirectoryHandle destinationDirectory, USVString newEntryName); }; From b4e132f0e29d0bb2127b189f8502484e682ce59e Mon Sep 17 00:00:00 2001 From: valadaptive Date: Sun, 4 Jan 2026 08:21:32 -0500 Subject: [PATCH 09/12] Move the `FileSystemFileHandle.move` section --- index.bs | 472 +++++++++++++++++++++++++++---------------------------- 1 file changed, 236 insertions(+), 236 deletions(-) diff --git a/index.bs b/index.bs index c843602..6184191 100644 --- a/index.bs +++ b/index.bs @@ -419,242 +419,6 @@ The isSameEntry(|other|) method steps are
-### The {{FileSystemFileHandle/move(destinationDirectory, newEntryName)|move()}} method ### {#api-filesystemhandle-move} - -
- : await fileHhandle| . {{FileSystemFileHandle/move(newEntryName)|move}}({ {{USVString}}: |newEntryName|}) - :: Renames the [=file system entry=] [=locate an entry|locatable=] by - |fileHandle|'s [=FileSystemHandle/locator=] to |newEntryName|. - - : await |fileHandle| . {{FileSystemFileHandle/move(destinationDirectory)|move}}({ {{FileSystemDirectoryHandle}}: |destinationDirectory|}) - :: Moves the [=file system entry=] [=locate an entry|locatable=] by - |fileHandle|'s [=FileSystemHandle/locator=] to the [=directory entry=] - [=locate an entry|locatable=] by |destinationDirectory|'s - [=FileSystemHandle/locator=], while keeping its existing name. - - If the [=file system locator/root|roots=] of the respective - [=FileSystemHandle/locator|locators=] of |destinationDirectory| and - |fileHandle| are not the same, this operation might abort or fail - non-atomically. - - : await |fileHandle| . {{FileSystemFileHandle/move(destinationDirectory, newEntryName)|move}}({ {{FileSystemDirectoryHandle}}: |destinationDirectory|, {{USVString}}: |newEntryName|}) - :: Moves the [=file system entry=] [=locate an entry|locatable=] by - |fileHandle|'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 - |fileHandle| are not the same, this operation might abort or fail - non-atomically. -
- -
-The move({{FileSystemDirectoryHandle}}: |destinationDirectory|) -method steps are to [=FileSystemFileHandle/move=] [=this=] -given [=this=]'s {{FileSystemHandle/name}} and |destinationDirectory|. - -
- -
-The move({{USVString}}: |newEntryName|) -method steps are to [=FileSystemFileHandle/move=] [=this=] -given |newEntryName|. - -
- -
-The move({{FileSystemDirectoryHandle}}: |destinationDirectory|, {{USVString}}: |newEntryName|) -method steps are to [=FileSystemFileHandle/move=] [=this=] -given |newEntryName| and |destinationDirectory|. - -
- -
- -To move a {{FileSystemFileHandle}} |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. 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. 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 - Web Locks API 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|. - - 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 |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 might result in a partially-written |destinationEntry|. - A directory move might result in only some files or sub-folders being - copied to |destinationEntry|, and some containing files might 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=]. 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|. - -
- ## The {{FileSystemFileHandle}} interface ## {#api-filesystemfilehandle} @@ -902,6 +666,242 @@ The <dfn method for=FileSystemFileHandle>createSyncAccessHandle()</dfn> method s </div> +### The {{FileSystemFileHandle/move(destinationDirectory, newEntryName)|move()}} method ### {#api-filesystemhandle-move} + +<div class="note domintro"> + : await fileHhandle| . {{FileSystemFileHandle/move(newEntryName)|move}}({ {{USVString}}: |newEntryName|}) + :: Renames the [=file system entry=] [=locate an entry|locatable=] by + |fileHandle|'s [=FileSystemHandle/locator=] to |newEntryName|. + + : await |fileHandle| . {{FileSystemFileHandle/move(destinationDirectory)|move}}({ {{FileSystemDirectoryHandle}}: |destinationDirectory|}) + :: Moves the [=file system entry=] [=locate an entry|locatable=] by + |fileHandle|'s [=FileSystemHandle/locator=] to the [=directory entry=] + [=locate an entry|locatable=] by |destinationDirectory|'s + [=FileSystemHandle/locator=], while keeping its existing name. + + If the [=file system locator/root|roots=] of the respective + [=FileSystemHandle/locator|locators=] of |destinationDirectory| and + |fileHandle| are not the same, this operation might abort or fail + non-atomically. + + : await |fileHandle| . {{FileSystemFileHandle/move(destinationDirectory, newEntryName)|move}}({ {{FileSystemDirectoryHandle}}: |destinationDirectory|, {{USVString}}: |newEntryName|}) + :: Moves the [=file system entry=] [=locate an entry|locatable=] by + |fileHandle|'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 + |fileHandle| are not the same, this operation might abort or fail + non-atomically. +</div> + +<div algorithm> +The <dfn method for=FileSystemFileHandle>move({{FileSystemDirectoryHandle}}: |destinationDirectory|)</dfn> +method steps are to [=FileSystemFileHandle/move=] [=this=] +given [=this=]'s {{FileSystemHandle/name}} and |destinationDirectory|. + +</div> + +<div algorithm> +The <dfn method for=FileSystemFileHandle>move({{USVString}}: |newEntryName|)</dfn> +method steps are to [=FileSystemFileHandle/move=] [=this=] +given |newEntryName|. + +</div> + +<div algorithm> +The <dfn method for=FileSystemFileHandle>move({{FileSystemDirectoryHandle}}: |destinationDirectory|, {{USVString}}: |newEntryName|)</dfn> +method steps are to [=FileSystemFileHandle/move=] [=this=] +given |newEntryName| and |destinationDirectory|. + +</div> + +<div algorithm> + +To <dfn for=FileSystemFileHandle>move</dfn> a {{FileSystemFileHandle}} |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. 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. 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|. + + 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 |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 might result in a partially-written |destinationEntry|. + A directory move might result in only some files or sub-folders being + copied to |destinationEntry|, and some containing files might 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=]. 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 {{FileSystemDirectoryHandle}} interface ## {#api-filesystemdirectoryhandle} <xmp class=idl> From 81c6fd8c863ddef3605427019db5695ac04ca33a Mon Sep 17 00:00:00 2001 From: valadaptive <valadaptive@protonmail.com> Date: Mon, 2 Mar 2026 04:48:17 -0500 Subject: [PATCH 10/12] Don't list algorithm types --- index.bs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.bs b/index.bs index 6184191..b110774 100644 --- a/index.bs +++ b/index.bs @@ -697,21 +697,21 @@ The <dfn method for=FileSystemFileHandle>createSyncAccessHandle()</dfn> method s </div> <div algorithm> -The <dfn method for=FileSystemFileHandle>move({{FileSystemDirectoryHandle}}: |destinationDirectory|)</dfn> +The <dfn method for=FileSystemFileHandle>move(|destinationDirectory|)</dfn> method steps are to [=FileSystemFileHandle/move=] [=this=] given [=this=]'s {{FileSystemHandle/name}} and |destinationDirectory|. </div> <div algorithm> -The <dfn method for=FileSystemFileHandle>move({{USVString}}: |newEntryName|)</dfn> +The <dfn method for=FileSystemFileHandle>move(|newEntryName|)</dfn> method steps are to [=FileSystemFileHandle/move=] [=this=] given |newEntryName|. </div> <div algorithm> -The <dfn method for=FileSystemFileHandle>move({{FileSystemDirectoryHandle}}: |destinationDirectory|, {{USVString}}: |newEntryName|)</dfn> +The <dfn method for=FileSystemFileHandle>move(|destinationDirectory|, |newEntryName|)</dfn> method steps are to [=FileSystemFileHandle/move=] [=this=] given |newEntryName| and |destinationDirectory|. From f2ed01cbae4f5700873ed92b2a3604c5cebda3bb Mon Sep 17 00:00:00 2001 From: valadaptive <valadaptive@protonmail.com> Date: Mon, 2 Mar 2026 05:01:35 -0500 Subject: [PATCH 11/12] Move destinationLockResult initialization --- index.bs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/index.bs b/index.bs index b110774..38c8cf8 100644 --- a/index.bs +++ b/index.bs @@ -825,13 +825,12 @@ given a {{USVString}} |newEntryName| and an optional 1. Let |lockResult| be the result of [=file entry/lock/take|taking a lock=] with "`exclusive`" on |entry|. + 1. Let |destinationLockResult| be "`not taken`". 1. If |destinationEntry| is not `null`: - 1. Let |destinationLockResult| be the result of + 1. Set |destinationLockResult| to 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. From cf9efc4214e22239f1e8494766885187c5db74dd Mon Sep 17 00:00:00 2001 From: valadaptive <valadaptive@protonmail.com> Date: Mon, 2 Mar 2026 05:04:53 -0500 Subject: [PATCH 12/12] Change `null` -> null --- index.bs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/index.bs b/index.bs index 38c8cf8..8ac640e 100644 --- a/index.bs +++ b/index.bs @@ -798,7 +798,7 @@ given a {{USVString}} |newEntryName| and an optional 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 + 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. @@ -817,17 +817,17 @@ given a {{USVString}} |newEntryName| and an optional [=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=] + 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| + 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|. 1. Let |destinationLockResult| be "`not taken`". - 1. If |destinationEntry| is not `null`: + 1. If |destinationEntry| is not null: 1. Set |destinationLockResult| to the result of [=file entry/lock/take|taking a lock=] with "`exclusive`" on |destinationEntry|. @@ -871,7 +871,7 @@ given a {{USVString}} |newEntryName| and an optional to |destinationEntry|. 1. If |destinationDirectory| was given: - 1. If |entry|'s [=file system entry/parent=] is not `null`, + 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=].