From 4f1893b286570fff8eb87d658eb2c27f7f1bc974 Mon Sep 17 00:00:00 2001 From: Austin Sullivan Date: Sat, 25 Feb 2023 01:31:20 +0000 Subject: [PATCH 01/12] map a FileSystemHandle to a path --- index.bs | 238 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 180 insertions(+), 58 deletions(-) diff --git a/index.bs b/index.bs index 4fce439..1de3ab2 100644 --- a/index.bs +++ b/index.bs @@ -15,6 +15,7 @@ spec:webidl; type:dfn; text:resolve
 urlPrefix: https://tc39.es/ecma262/; spec: ECMA-262
+  type: dfn; text: current realm; url: current realm
   type: dfn; text: realm; url: realm
 urlPrefix: https://storage.spec.whatwg.org/; spec: storage
   type: dfn; text: storage; url: site-storage
@@ -59,6 +60,8 @@ different storage mechanism with a different API for such files. The entry point
 
 A file system entry is either a [=file entry=] or a [=directory entry=].
 
+
+
 Each [=/file system entry=] has an associated query access algorithm, which takes "`read`"
 or "`readwrite`" mode and returns a {{PermissionState}}. Unless specified
 otherwise it returns "{{PermissionState/denied}}". The algorithm is allowed to throw.
@@ -90,6 +93,8 @@ A file entry additionally consists of
 a lock (a string that may exclusively be "`open`", "`taken-exclusive`" or "`taken-shared`")
 and a shared lock count (a number representing the number shared locks that are taken at a given point in time).
 
+
+
 
To take a [=file entry/lock=] with a |value| of "`exclusive`" or "`shared`" on a given [=file entry=] |file|: @@ -147,11 +152,9 @@ Exactly how external changes are reflected in the data structures defined by thi as well as how changes made to the data structures defined here are reflected externally is left up to individual user-agent implementations. -A [=/file system entry=] |a| is the same as an [=/file system entry=] |b| if |a| is equal to |b|, or -if |a| and |b| are backed by the same file or directory on the local file system. - -Issue(59): Explain better how entries map to files on disk (multiple entries can map to the same file or -directory on disk but an entry doesn't have to map to any file on disk). +A [=/file system entry=] |a| is the same entry as +a [=/file system entry=] |b| if |a| is equal to |b|, or if |a| and |b| are +backed by the same file or directory on the local file system.
@@ -160,7 +163,7 @@ run these steps: 1. Let |result| be [=a new promise=]. 1. Run these steps [=in parallel=]: - 1. If |child| is [=the same as=] |root|, + 1. If |child| is [=the same entry as=] |root|, [=/resolve=] |result| with an empty list, and abort. 1. Let |childPromises| be « ». 1. [=set/For each=] |entry| of |root|'s [=FileSystemHandle/entry=]'s [=children=]: @@ -176,6 +179,33 @@ run these steps:
+A file system path represents a potential location of a +[=/file system entry=]. For example, this may be to a virtual path that is +mapped to real location on disk or in memory, may correspond directly to a +path on the local file system, or may not correspond to any file on disk at all. + +The locate algorithm takes a [=/file system path=] and +returns either a [=/file system entry=] or `null`. The steps of this algorithm +are [=implementation-defined=]. + +The get the path algorithm takes a +[=/file system entry=] and returns a [=/file system path=]. +If [=locating=] a [=/file system path=] |path| returns a [=/file system entry=] |entry|, +then [=getting the path=] of |entry| must return |path|. + +Each [=/file system path=] has an associated name (a [=string=]), +which represents the last path component of the file path. For example, if +[=/file system path=] |path| corresponds to a location represented by a +virtual path of `data/drafts/example.txt` relative to the root directory of an +[=origin private file system=], |path|'s [=file system path/name=] should be `example.txt`. + +If [=locating=] a [=/file system path=] |path| returns a [=/file system entry=] |entry|, then +|path|'s [=file system path/name=] must equal |entry|'s [=file system entry/name=]. + +A [=/file system path=] |a| is the same path as +a [=/file system path=] |b| if |a| represents the same potential location of a +[=/file system entry=] as |b|. + ## The {{FileSystemHandle}} interface ## {#api-filesystemhandle} @@ -193,9 +223,18 @@ interface FileSystemHandle { }; -A {{FileSystemHandle}} object represents a [=/file system entry=]. Each {{FileSystemHandle}} object is associated -with an entry (a [=/file system entry=]). Multiple separate objects implementing -the {{FileSystemHandle}} interface can all be associated with the same [=/file system entry=] simultaneously. +A {{FileSystemHandle}} object represents a [=/file system path=]. +Each {{FileSystemHandle}} object is associated with a +path (a [=/file system path=]). +Multiple separate objects implementing the {{FileSystemHandle}} interface can +all be associated with the same [=/file system path=] simultaneously. + +
+To get the entry +of a given {{FileSystemHandle}} |handle|, return the result of running +[=locate=] given |handle|'s [=FileSystemHandle/path=]. + +
{{FileSystemHandle}} objects are [=serializable objects=]. @@ -203,7 +242,7 @@ the {{FileSystemHandle}} interface can all be associated with the same [=/file s Their [=serialization steps=], given |value|, |serialized| and forStorage are: 1. Set |serialized|.\[[Origin]] to |value|'s [=relevant settings object=]'s [=environment settings object/origin=]. -1. Set |serialized|.\[[Entry]] to |value|'s [=FileSystemHandle/entry=]. +1. Set |serialized|.\[[Path]] to |value|'s [=FileSystemHandle/path=].
@@ -213,7 +252,7 @@ Their [=deserialization steps=], given |serialized| and |value| are: 1. If |serialized|.\[[Origin]] is not [=same origin=] with |value|'s [=relevant settings object=]'s [=environment settings object/origin=], then [=throw=] a "{{DataCloneError}}" {{DOMException}}. -1. Set |value|'s [=FileSystemHandle/entry=] to |serialized|.\[[Entry]] +1. Set |value|'s [=FileSystemHandle/path=] to |serialized|.\[[Path]]
@@ -226,14 +265,15 @@ Their [=deserialization steps=], given |serialized| and |value| are: of a directory. : |handle| . {{FileSystemHandle/name}} - :: Returns the [=file system entry/name=] of the entry represented by |handle|. + :: Returns the last path component of |handle|'s [=FileSystemHandle/path=]. The kind getter steps are to return {{FileSystemHandleKind/"file"}} if [=this=] is a [=file entry=]; otherwise {{FileSystemHandleKind/"directory"}}. -The name getter steps are to return [=this=]'s [=file system entry/name=]. +The name getter steps are to return +[=this=]'s [=FileSystemHandle/path=]'s [=file system path/name=]. ### The {{FileSystemHandle/isSameEntry()}} method ### {#api-filesystemhandle-issameentry} @@ -248,7 +288,7 @@ The isSameEntry(|other|) method steps are 1. Let |realm| be [=this=]'s [=relevant Realm=]. 1. Let |p| be [=a new promise=] in |realm|. 1. Run these steps [=in parallel=]: - 1. If [=this=]'s [=FileSystemHandle/entry=] is [=the same as=] |other|'s [=FileSystemHandle/entry=], + 1. If [=this=]'s [=FileSystemHandle/path=] is [=the same path as=] |other|'s [=FileSystemHandle/path=], [=/resolve=] |p| with true. 1. Otherwise [=/resolve=] |p| with false. 1. Return |p|. @@ -271,7 +311,18 @@ interface FileSystemFileHandle : FileSystemHandle { }; -A {{FileSystemFileHandle}}'s associated [=FileSystemHandle/entry=] must be a [=file entry=]. +A {{FileSystemFileHandle}}'s associated [=FileSystemHandle/path=] +is expected to [=locate=] a [=file entry=]. + +
+To create a new FileSystemFileHandle +given a [=file entry=] |entry| in a [=/Realm=] |realm|, run these steps: + +1. Let |handle| be a [=new=] {{FileSystemFileHandle}} in |realm|. +1. Set |handle|'s [=FileSystemHandle/path=] to the result of [=getting the path=] of |entry|. +1. Return |handle|. + +
{{FileSystemFileHandle}} objects are [=serializable objects=]. Their [=serialization steps=] and [=deserialization steps=] are the same as those for {{FileSystemHandle}}. @@ -280,7 +331,8 @@ A {{FileSystemFileHandle}}'s associated [=FileSystemHandle/entry=] must be a [=f
: file = await |fileHandle| . {{FileSystemFileHandle/getFile()}} - :: Returns a {{File}} representing the state on disk of the entry represented by |handle|. + :: Returns a {{File}} representing the state on disk of the [=file entry=] + [=locate|locatable=] by |handle|'s [=FileSystemHandle/path=]. If the file on disk changes or is removed after this method is called, the returned {{File}} object will likely be no longer readable.
@@ -289,12 +341,18 @@ A {{FileSystemFileHandle}}'s associated [=FileSystemHandle/entry=] must be a [=f The getFile() method steps are: 1. Let |result| be [=a new promise=]. +1. Let |entry| be the the result of [=getting the entry=] for [=this=]. 1. Run these steps [=in parallel=]: 1. Let |access| be the result of running [=this=]'s [=FileSystemHandle/entry=]'s [=file system entry/query access=] given "`read`". 1. If |access| is not "{{PermissionState/granted}}", [=/reject=] |result| with a "{{NotAllowedError}}" {{DOMException}} and abort. - 1. Let |entry| be [=this=]'s [=FileSystemHandle/entry=]. + + 1. If |entry| is `null`, [=/reject=] |result| with a + "{{NotFoundError}}" {{DOMException}} and abort. + 1. If |entry| is not a [=file entry=] [=/reject=] |result| with a + "{{TypeMismatchError}}" {{DOMException}} and abort. + 1. Let |f| be a new {{File}}. 1. Set |f|'s snapshot state to the current state of |entry|. 1. Set |f|'s underlying byte sequence to a copy of |entry|'s [=binary data=]. @@ -315,21 +373,24 @@ The getFile() method steps are: : |stream| = await |fileHandle| . {{FileSystemFileHandle/createWritable()}} : |stream| = await |fileHandle| . {{FileSystemFileHandle/createWritable()|createWritable}}({ {{FileSystemCreateWritableOptions/keepExistingData}}: true/false }) :: Returns a {{FileSystemWritableFileStream}} that can be used to write to the file. Any changes made through - |stream| won't be reflected in the file represented by |fileHandle| until the stream has been closed. - User agents try to ensure that no partial writes happen, i.e. the file represented by - |fileHandle| will either contain its old contents or it will contain whatever data was written + |stream| won't be reflected in the [=file entry=] [=locate|locatable=] by + |fileHandle|'s [=FileSystemHandle/path=] until the stream has been closed. + User agents try to ensure that no partial writes happen, i.e. the file + will either contain its old contents or it will contain whatever data was written through |stream| up until the stream has been closed. - This is typically implemented by writing data to a temporary file, and only replacing the file - represented by |fileHandle| with the temporary file when the writable filestream is closed. + This is typically implemented by writing data to a temporary file, and only replacing the + [=file entry=] [=locate|locatable=] by |fileHandle|'s [=FileSystemHandle/path=] + with the temporary file when the writable filestream is closed. If {{FileSystemCreateWritableOptions/keepExistingData}} is false or not specified, the temporary file starts out empty, otherwise the existing file is first copied to this temporary file. Creating a {{FileSystemWritableFileStream}} [=file entry/lock/take|takes a shared lock=] on the - [=FileSystemHandle/entry=] associated with |fileHandle|. This prevents the creation of - {{FileSystemSyncAccessHandle|FileSystemSyncAccessHandles}} for the entry, until the stream is closed. + [=file entry=] [=locate|locatable=] with |fileHandle|'s [=FileSystemHandle/path=]. + This prevents the creation of {{FileSystemSyncAccessHandle|FileSystemSyncAccessHandles}} + for the entry, until the stream is closed.

See WICG/file-system-access issue #67 @@ -346,13 +407,19 @@ private file system=] via the {{FileSystemSyncAccessHandle}} interface. The createWritable(|options|) method steps are: 1. Let |result| be [=a new promise=]. +1. Let |entry| be the the result of [=getting the entry=] for [=this=]. 1. Run these steps [=in parallel=]: 1. Let |access| be the result of running [=this=]'s [=FileSystemHandle/entry=]'s [=file system entry/request access=] given "`readwrite`". If that throws an exception, [=reject=] |result| with that exception and abort. 1. If |access| is not "{{PermissionState/granted}}", [=reject=] |result| with a "{{NotAllowedError}}" {{DOMException}} and abort. - 1. Let |entry| be [=this=]'s [=FileSystemHandle/entry=]. + + 1. If |entry| is `null`, [=/reject=] |result| with a + "{{NotFoundError}}" {{DOMException}} and abort. + 1. If |entry| is not a [=file entry=], [=/reject=] |result| with a + "{{TypeMismatchError}}" {{DOMException}} and abort. + 1. Let |lockResult| be the result of [=file entry/lock/take|taking a lock=] with "`shared`" on |entry|. 1. If |lockResult| is false, [=reject=] |result| with a "{{NoModificationAllowedError}}" {{DOMException}} and abort. 1. Let |stream| be the result of creating a new FileSystemWritableFileStream @@ -369,12 +436,14 @@ The createWritable(|options|) method

: |handle| = await |fileHandle| . {{FileSystemFileHandle/createSyncAccessHandle()|createSyncAccessHandle}}() :: Returns a {{FileSystemSyncAccessHandle}} that can be used to read from/write to the file. - Changes made through |handle| might be immediately reflected in the file represented by |fileHandle|. + Changes made through |handle| might be immediately reflected in the + [=file entry=] [=locate|locatable=] by |fileHandle|'s [=FileSystemHandle/path=]. To ensure the changes are reflected in this file, the handle can be flushed. Creating a {{FileSystemSyncAccessHandle}} [=file entry/lock/take|takes an exclusive lock=] on the - [=FileSystemHandle/entry=] associated with |fileHandle|. This prevents the creation of - further {{FileSystemSyncAccessHandle}}s or {{FileSystemWritableFileStream}}s + [=file entry=] [=locate|locatable=] with |fileHandle|'s [=FileSystemHandle/path=]. + This prevents the creation of further {{FileSystemSyncAccessHandle|FileSystemSyncAccessHandles}} + or {{FileSystemWritableFileStream|FileSystemWritableFileStreams}} for the entry, until the access handle is closed. The returned {{FileSystemSyncAccessHandle}} offers synchronous methods. This allows for higher performance @@ -388,13 +457,19 @@ The createWritable(|options|) method The createSyncAccessHandle() method steps are: 1. Let |result| be [=a new promise=]. +1. Let |entry| be the the result of [=getting the entry=] for [=this=]. 1. Run these steps [=in parallel=]: 1. Let |access| be the result of running [=this=]'s [=FileSystemHandle/entry=]'s [=file system entry/request access=] given "`readwrite`". If that throws an exception, [=reject=] |result| with that exception and abort. 1. If |access| is not "{{PermissionState/granted}}", [=reject=] |result| with a "{{NotAllowedError}}" {{DOMException}} and abort. - 1. Let |entry| be [=this=]'s [=FileSystemHandle/entry=]. + + 1. If |entry| is `null`, [=/reject=] |result| with a + "{{NotFoundError}}" {{DOMException}} and abort. + 1. If |entry| is not a [=file entry=], [=/reject=] |result| with a + "{{TypeMismatchError}}" {{DOMException}} and abort. + 1. If |entry| does not represent a [=/file system entry=] in an [=origin private file system=], [=reject=] |result| with an "{{InvalidStateError}}" {{DOMException}} and abort. 1. Let |lockResult| be the result of [=file entry/lock/take|taking a lock=] with "`exclusive`" on |entry|. @@ -434,7 +509,18 @@ interface FileSystemDirectoryHandle : FileSystemHandle { }; -A {{FileSystemDirectoryHandle}}'s associated [=FileSystemHandle/entry=] must be a [=directory entry=]. +A {{FileSystemDirectoryHandle}}'s associated [=FileSystemHandle/path=] +is expected to [=locate=] a [=directory entry=]. + +
+To create a new FileSystemDirectoryHandle +given a [=directory entry=] |entry| in a [=/Realm=] |realm|, run these steps: + +1. Let |handle| be a [=new=] {{FileSystemDirectoryHandle}} in |realm|. +1. Set |handle|'s [=FileSystemHandle/path=] to the result of [=getting the path=] of |entry|. +1. Return |handle|. + +
{{FileSystemDirectoryHandle}} objects are [=serializable objects=]. Their [=serialization steps=] and [=deserialization steps=] are the same as those for {{FileSystemHandle}}. @@ -446,9 +532,10 @@ A {{FileSystemDirectoryHandle}}'s associated [=FileSystemHandle/entry=] must be : for await (let [|name|, |handle|] of |directoryHandle| . entries()) {} : for await (let |handle| of |directoryHandle| . values()) {} : for await (let |name| of |directoryHandle| . keys()) {} - :: Iterates over all entries whose parent is the entry represented by |directoryHandle|. Entries - that are created or deleted while the iteration is in progress might or might not be included. - No guarantees are given either way. + :: Iterates over all entries whose parent is the [=directory entry=] + [=locate|locatable=] by |directoryHandle|'s [=FileSystemHandle/path=]. + Entries that are created or deleted while the iteration is in progress + might or might not be included. No guarantees are given either way.
Issue(15): In the future we might want to add arguments to the async iterable declaration to @@ -474,7 +561,11 @@ and its async iterator |iterator|: 1. Let |promise| be [=a new promise=]. -1. Let |directory| be |handle|'s [=FileSystemHandle/entry=]. +1. Let |directory| be the the result of [=getting the entry=] for |handle|. +1. If |directory| is `null`, [=/reject=] |result| with a + "{{NotFoundError}}" {{DOMException}} and abort. +1. If |directory| is not a [=directory entry=], [=/reject=] |result| with a + "{{TypeMismatchError}}" {{DOMException}} and abort. 1. Let |access| be the result of running |handle|'s [=FileSystemHandle/entry=]'s [=file system entry/query access=] given "`read`". @@ -498,9 +589,11 @@ and its async iterator |iterator|: 1. Otherwise: 1. [=set/Append=] |child|'s [=file system entry/name=] to |iterator|'s [=past results=]. 1. If |child| is a [=file entry=]: - 1. Let |result| be a new {{FileSystemFileHandle}} associated with |child|. + 1. Let |result| be the result of [=creating a new FileSystemFileHandle=] + with |child| in |handle|'s [=relevant Realm=]. 1. Otherwise: - 1. Let |result| be a new {{FileSystemDirectoryHandle}} associated with |child|. + 1. Let |result| be the result of [=creating a new FileSystemDirectoryHandle=] + with |child| in |handle|'s [=relevant Realm=]. 1. [=/Resolve=] |promise| with (|child|'s [=file system entry/name=], |result|). 1. Return |promise|. @@ -512,12 +605,14 @@ and its async iterator |iterator|:
: |fileHandle| = await |directoryHandle| . {{FileSystemDirectoryHandle/getFileHandle()|getFileHandle}}(|name|) : |fileHandle| = await |directoryHandle| . {{FileSystemDirectoryHandle/getFileHandle()|getFileHandle}}(|name|, { {{FileSystemGetFileOptions/create}}: false }) - :: Returns a handle for a file named |name| in the directory represented by |directoryHandle|. If - no such file exists, this rejects. + :: Returns a handle for a file named |name| in the [=directory entry=] + [=locate|locatable=] by |directoryHandle|'s [=FileSystemHandle/path=]. + If no such file exists, this rejects. : |fileHandle| = await |directoryHandle| . {{FileSystemDirectoryHandle/getFileHandle()|getFileHandle}}(|name|, { {{FileSystemGetFileOptions/create}}: true }) - :: Returns a handle for a file named |name| in the directory represented by |directoryHandle|. If - no such file exists, this creates a new file. If no file with named |name| can be created this + :: Returns a handle for a file named |name| in the [=directory entry=] + [=locate|locatable=] by |directoryHandle|'s [=FileSystemHandle/path=]. + If no such file exists, this creates a new file. If no file with named |name| can be created this rejects. Creation can fail because there already is a directory with the same name, because the name uses characters that aren't supported in file names on the underlying file system, or because the user agent for security reasons decided not to allow creation of the file. @@ -532,10 +627,11 @@ and its async iterator |iterator|: The getFileHandle(|name|, |options|) method steps are: 1. Let |result| be [=a new promise=]. +1. Let |realm| be [=this=]'s [=relevant Realm=]. +1. Let |entry| be the the result of [=getting the entry=] for [=this=]. 1. Run these steps [=in parallel=]: 1. If |name| is not a [=valid file name=], [=/reject=] |result| with a {{TypeError}} and abort. - 1. Let |entry| be [=this=]'s [=FileSystemHandle/entry=]. 1. If |options|.{{FileSystemGetFileOptions/create}} is true: 1. Let |access| be the result of running [=this=]'s [=FileSystemHandle/entry=]'s [=file system entry/request access=] given "`readwrite`". @@ -546,11 +642,17 @@ The getFileHandle(|name|, |options|)getFileHandle(|name|, |options|) @@ -573,12 +676,14 @@ The getFileHandle(|name|, |options|) : |subdirHandle| = await |directoryHandle| . {{FileSystemDirectoryHandle/getDirectoryHandle()|getDirectoryHandle}}(|name|) : |subdirHandle| = await |directoryHandle| . {{FileSystemDirectoryHandle/getDirectoryHandle()|getDirectoryHandle}}(|name|, { {{FileSystemGetDirectoryOptions/create}}: false }) - :: Returns a handle for a directory named |name| in the directory represented by - |directoryHandle|. If no such directory exists, this rejects. + :: Returns a handle for a directory named |name| in the [=directory entry=] + [=locate|locatable=] by |directoryHandle|'s [=FileSystemHandle/path=]. + If no such directory exists, this rejects. : |subdirHandle| = await |directoryHandle| . {{FileSystemDirectoryHandle/getDirectoryHandle()|getDirectoryHandle}}(|name|, { {{FileSystemGetDirectoryOptions/create}}: true }) - :: Returns a handle for a directory named |name| in the directory represented by - |directoryHandle|. If no such directory exists, this creates a new directory. If creating the + :: Returns a handle for a directory named |name| in the [=directory entry=] + [=locate|locatable=] by |directoryHandle|'s [=FileSystemHandle/path=] . + If no such directory exists, this creates a new directory. If creating the directory failed, this rejects. Creation can fail because there already is a file with the same name, or because the name uses characters that aren't supported in file names on the underlying file system. @@ -593,10 +698,11 @@ The getFileHandle(|name|, |options|)getDirectoryHandle(|name|, |options|) method steps are: 1. Let |result| be [=a new promise=]. +1. Let |realm| be [=this=]'s [=relevant Realm=]. +1. Let |entry| be the the result of [=getting the entry=] for [=this=]. 1. Run these steps [=in parallel=]: 1. If |name| is not a [=valid file name=], [=/reject=] |result| with a {{TypeError}} and abort. - 1. Let |entry| be [=this=]'s [=FileSystemHandle/entry=]. 1. If |options|.{{FileSystemGetDirectoryOptions/create}} is true: 1. Let |access| be the result of running [=this=]'s [=FileSystemHandle/entry=]'s [=file system entry/request access=] given "`readwrite`". @@ -607,11 +713,17 @@ The getDirectoryHandle(|name|, |option 1. If |access| is not "{{PermissionState/granted}}", [=/reject=] |result| with a "{{NotAllowedError}}" {{DOMException}} and abort. + 1. If |entry| is `null`, [=/reject=] |result| with a + "{{NotFoundError}}" {{DOMException}} and abort. + 1. If |entry| is not a [=directory entry=], [=/reject=] |result| with a + "{{TypeMismatchError}}" {{DOMException}} and abort. + 1. [=set/For each=] |child| of |entry|'s [=directory entry/children=]: 1. If |child|'s [=file system entry/name=] equals |name|: 1. If |child| is a [=file entry=]: 1. [=/Reject=] |result| with a "{{TypeMismatchError}}" {{DOMException}} and abort. - 1. [=/Resolve=] |result| with a new {{FileSystemDirectoryHandle}} whose [=FileSystemHandle/entry=] is |child| and abort. + 1. [=/Resolve=] |result| with the result of + [=creating a new FileSystemDirectoryHandle=] with |child| in |realm| and abort. 1. If |options|.{{FileSystemGetFileOptions/create}} is false: 1. [=/Reject=] |result| with a "{{NotFoundError}}" {{DOMException}} and abort. 1. Let |child| be a new [=directory entry=] whose [=query access=] and [=request access=] @@ -623,7 +735,8 @@ The getDirectoryHandle(|name|, |option [=/reject=] |result| with that exception and abort. Issue(11): Better specify what possible exceptions this could throw. - 1. [=/Resolve=] |result| with a new {{FileSystemDirectoryHandle}} whose [=FileSystemHandle/entry=] is |child|. + 1. [=/Resolve=] |result| with the result of + [=creating a new FileSystemDirectoryHandle=] with |child| in |realm|. 1. Return |result|.
@@ -633,14 +746,16 @@ The getDirectoryHandle(|name|, |option
: await |directoryHandle| . {{FileSystemDirectoryHandle/removeEntry()|removeEntry}}(|name|) : await |directoryHandle| . {{FileSystemDirectoryHandle/removeEntry()|removeEntry}}(|name|, { {{FileSystemRemoveOptions/recursive}}: false }) - :: If the directory represented by |directoryHandle| contains a file named |name|, or an empty + :: If the [=directory entry=] [=locate|locatable=] by |directoryHandle|'s + [=FileSystemHandle/path=] contains a file named |name|, or an empty directory named |name|, this will attempt to delete that file or directory. Attempting to delete a file or directory that does not exist is considered success, while attempting to delete a non-empty directory will result in a promise rejection. : await |directoryHandle| . {{FileSystemDirectoryHandle/removeEntry()|removeEntry}}(|name|, { {{FileSystemRemoveOptions/recursive}}: true }) - :: Removes the entry named |name| in the directory represented by |directoryHandle|. + :: Removes the [=/file system entry=] named |name| in the [=directory entry=] + [=locate|locatable=] by |directoryHandle|'s [=FileSystemHandle/path=]. If that entry is a directory, its contents will also be deleted recursively. Attempting to delete a file or directory that does not exist is considered success. @@ -650,16 +765,21 @@ The getDirectoryHandle(|name|, |option The removeEntry(|name|, |options|) method steps are: 1. Let |result| be [=a new promise=]. +1. Let |entry| be the the result of [=getting the entry=] for [=this=]. 1. Run these steps [=in parallel=]: 1. If |name| is not a [=valid file name=], [=/reject=] |result| with a {{TypeError}} and abort. - 1. Let |entry| be [=this=]'s [=FileSystemHandle/entry=]. 1. Let |access| be the result of running [=this=]'s [=FileSystemHandle/entry=]'s [=file system entry/request access=] given "`readwrite`". If that throws an exception, [=reject=] |result| with that exception and abort. 1. If |access| is not "{{PermissionState/granted}}", [=/reject=] |result| with a "{{NotAllowedError}}" {{DOMException}} and abort. + 1. If |entry| is `null`, [=/reject=] |result| with a + "{{NotFoundError}}" {{DOMException}} and abort. + 1. If |entry| is not a [=directory entry=], [=/reject=] |result| with a + "{{TypeMismatchError}}" {{DOMException}} and abort. + 1. [=set/For each=] |child| of |entry|'s [=directory entry/children=]: 1. If |child|'s [=file system entry/name=] equals |name|: 1. If |child| is a [=directory entry=]: @@ -725,9 +845,11 @@ if (relative_path === null) {
-The resolve(|possibleDescendant|) method steps are -to return the result of [=file system entry/resolving=] |possibleDescendant|'s [=FileSystemHandle/entry=] -relative to [=this=]'s [=FileSystemHandle/entry=]. +The resolve(|possibleDescendant|) method steps are: + +1. Let |entry| be the the result of [=getting the entry=] for [=this=]. +1. Let |possibleDescendantEntry| be the the result of [=getting the entry=] for |possibleDescendant|. +1. Return the result of [=file system entry/resolving=] |possibleDescendantEntry| relative to |entry|.
@@ -1305,8 +1427,8 @@ The getDirectory() method steps are: 1. Set |dir|'s [=directory entry/children=] to an empty [=/set=]. 1. Set |map|["root"] to |dir|. -1. Return [=a promise resolved with=] a new {{FileSystemDirectoryHandle}}, - whose associated [=FileSystemHandle/entry=] is |map|["root"]. +1. Return [=a promise resolved with=] the result of + [=creating a new FileSystemDirectoryHandle=] with |map|["root"] in the [=current realm=]. From 1e72f06329d24200a28eb5bf1efd6b7e4df66e7b Mon Sep 17 00:00:00 2001 From: Austin Sullivan Date: Thu, 2 Mar 2023 00:11:31 +0000 Subject: [PATCH 02/12] address some nits --- index.bs | 53 +++++++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/index.bs b/index.bs index 1de3ab2..3537029 100644 --- a/index.bs +++ b/index.bs @@ -60,8 +60,6 @@ different storage mechanism with a different API for such files. The entry point A file system entry is either a [=file entry=] or a [=directory entry=]. - - Each [=/file system entry=] has an associated query access algorithm, which takes "`read`" or "`readwrite`" mode and returns a {{PermissionState}}. Unless specified otherwise it returns "{{PermissionState/denied}}". The algorithm is allowed to throw. @@ -93,8 +91,6 @@ A file entry additionally consists of a lock (a string that may exclusively be "`open`", "`taken-exclusive`" or "`taken-shared`") and a shared lock count (a number representing the number shared locks that are taken at a given point in time). - -
To take a [=file entry/lock=] with a |value| of "`exclusive`" or "`shared`" on a given [=file entry=] |file|: @@ -153,8 +149,8 @@ as well as how changes made to the data structures defined here are reflected ex is left up to individual user-agent implementations. A [=/file system entry=] |a| is the same entry as -a [=/file system entry=] |b| if |a| is equal to |b|, or if |a| and |b| are -backed by the same file or directory on the local file system. +a [=/file system entry=] |b| if |a| is equal to |b|, or if [=getting the path=] +of |a| returns [=the same path as=] [=getting the path=] of |b|.
@@ -174,37 +170,45 @@ run these steps: 1. [=list/Prepend=] |entry|'s [=file system entry/name=] to |path|. 1. [=/Resolve=] |result| with |path|. 1. [=Wait for all=] |childPromises|, with the these success steps: - 1. If |result| hasn't been resolved yet, [=/resolve=] |result| with `null`. + 1. If |result| hasn't been resolved yet, [=/resolve=] |result| with null. 1. Return |result|.
-A file system path represents a potential location of a -[=/file system entry=]. For example, this may be to a virtual path that is -mapped to real location on disk or in memory, may correspond directly to a -path on the local file system, or may not correspond to any file on disk at all. +A file system path is an opaque string that represents a +potential location of a [=/file system entry=]. +For example, this may be a virtual path that is mapped to real location on disk +or in memory, may correspond directly to a path on the local file system, or may +not correspond to any file on disk at all. The locate algorithm takes a [=/file system path=] and -returns either a [=/file system entry=] or `null`. The steps of this algorithm +returns either a [=/file system entry=] or null. The steps of this algorithm are [=implementation-defined=]. The get the path algorithm takes a [=/file system entry=] and returns a [=/file system path=]. -If [=locating=] a [=/file system path=] |path| returns a [=/file system entry=] |entry|, -then [=getting the path=] of |entry| must return |path|. - -Each [=/file system path=] has an associated name (a [=string=]), -which represents the last path component of the file path. For example, if -[=/file system path=] |path| corresponds to a location represented by a -virtual path of `data/drafts/example.txt` relative to the root directory of an -[=origin private file system=], |path|'s [=file system path/name=] should be `example.txt`. +If [=locating=] a [=/file system path=] |path| returns a [=/file system entry=] +|entry|, then [=getting the path=] of |entry| must return |path| if no +intermediate file system operations were run. Typically the steps are symmetric +to the [=locate=] algorithm. + +Each [=/file system path=] has an associated name (a [=string=]). +If [=locating=] [=/file system path=] |path| returns a +[=/file system entry=] |entry|, then |entry|'s [=file system entry/name=] +must be the same as |path|'s[=file system path/name=]. + +Note: This generally represents the last path component of the file path as +perceived by the user. For example, if [=/file system path=] |path| corresponds +to a location represented by a virtual path of `data/drafts/example.txt` +relative to the root directory of an [=origin private file system=], |path|'s +[=file system path/name=] should be `example.txt`. There is no expectation, +however, that a file called `example.txt` lives anywhere on disk. If [=locating=] a [=/file system path=] |path| returns a [=/file system entry=] |entry|, then |path|'s [=file system path/name=] must equal |entry|'s [=file system entry/name=]. A [=/file system path=] |a| is the same path as -a [=/file system path=] |b| if |a| represents the same potential location of a -[=/file system entry=] as |b|. +a [=/file system path=] |b| if |a| is |b|. ## The {{FileSystemHandle}} interface ## {#api-filesystemhandle} @@ -226,8 +230,9 @@ interface FileSystemHandle { A {{FileSystemHandle}} object represents a [=/file system path=]. Each {{FileSystemHandle}} object is associated with a path (a [=/file system path=]). -Multiple separate objects implementing the {{FileSystemHandle}} interface can -all be associated with the same [=/file system path=] simultaneously. + +Note: Multiple {{FileSystemHandle}} objects can have +[=the same path as|the same=] [=path=].
To get the entry From ba0aa30918ad4a90f2cdfdabbfb0d7592d5b3ff2 Mon Sep 17 00:00:00 2001 From: Austin Sullivan Date: Fri, 3 Mar 2023 06:18:08 +0000 Subject: [PATCH 03/12] introduce "file system locator" --- index.bs | 230 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 116 insertions(+), 114 deletions(-) diff --git a/index.bs b/index.bs index 3537029..2465655 100644 --- a/index.bs +++ b/index.bs @@ -60,6 +60,8 @@ different storage mechanism with a different API for such files. The entry point A file system entry is either a [=file entry=] or a [=directory entry=]. + + Each [=/file system entry=] has an associated query access algorithm, which takes "`read`" or "`readwrite`" mode and returns a {{PermissionState}}. Unless specified otherwise it returns "{{PermissionState/denied}}". The algorithm is allowed to throw. @@ -148,67 +150,70 @@ Exactly how external changes are reflected in the data structures defined by thi as well as how changes made to the data structures defined here are reflected externally is left up to individual user-agent implementations. -A [=/file system entry=] |a| is the same entry as -a [=/file system entry=] |b| if |a| is equal to |b|, or if [=getting the path=] -of |a| returns [=the same path as=] [=getting the path=] of |b|. -
-To resolve a [=/file system entry=] |child| relative to a [=directory entry=] |root|, +To resolve a +[=/file system locator=] |child| relative to a [=directory locator=] |root|, run these steps: 1. Let |result| be [=a new promise=]. 1. Run these steps [=in parallel=]: - 1. If |child| is [=the same entry as=] |root|, + 1. If |child|'s [=FileSystemHandle/locator=] is [=the same locator as=] + |root|'s [=FileSystemHandle/locator=], [=/resolve=] |result| with an empty list, and abort. - 1. Let |childPromises| be « ». - 1. [=set/For each=] |entry| of |root|'s [=FileSystemHandle/entry=]'s [=children=]: - 1. Let |p| be the result of [=file system entry/resolving=] |child| relative to |entry|. - 1. [=list/Append=] |p| to |childPromises|. - 1. [=Upon fulfillment=] of |p| with value |path|: - 1. If |path| is not null: - 1. [=list/Prepend=] |entry|'s [=file system entry/name=] to |path|. - 1. [=/Resolve=] |result| with |path|. - 1. [=Wait for all=] |childPromises|, with the these success steps: - 1. If |result| hasn't been resolved yet, [=/resolve=] |result| with null. + + + 1. Return |result|.
-A file system path is an opaque string that represents a -potential location of a [=/file system entry=]. -For example, this may be a virtual path that is mapped to real location on disk -or in memory, may correspond directly to a path on the local file system, or may -not correspond to any file on disk at all. - -The locate algorithm takes a [=/file system path=] and -returns either a [=/file system entry=] or null. The steps of this algorithm -are [=implementation-defined=]. - -The get the path algorithm takes a -[=/file system entry=] and returns a [=/file system path=]. -If [=locating=] a [=/file system path=] |path| returns a [=/file system entry=] -|entry|, then [=getting the path=] of |entry| must return |path| if no -intermediate file system operations were run. Typically the steps are symmetric -to the [=locate=] algorithm. - -Each [=/file system path=] has an associated name (a [=string=]). -If [=locating=] [=/file system path=] |path| returns a -[=/file system entry=] |entry|, then |entry|'s [=file system entry/name=] -must be the same as |path|'s[=file system path/name=]. - -Note: This generally represents the last path component of the file path as -perceived by the user. For example, if [=/file system path=] |path| corresponds -to a location represented by a virtual path of `data/drafts/example.txt` -relative to the root directory of an [=origin private file system=], |path|'s -[=file system path/name=] should be `example.txt`. There is no expectation, -however, that a file called `example.txt` lives anywhere on disk. - -If [=locating=] a [=/file system path=] |path| returns a [=/file system entry=] |entry|, then -|path|'s [=file system path/name=] must equal |entry|'s [=file system entry/name=]. - -A [=/file system path=] |a| is the same path as -a [=/file system path=] |b| if |a| is |b|. +A file system locator represents a potential location of a +[=/file system entry=]. A [=/file system locator=] is either a [=file locator=] +or a [=directory locator=]. + +Each [=/file system locator=] has an associated path (a [=/file system path=]) +and an associated kind (a {{FileSystemHandleKind}}). + +A file locator is a [=/file system locator=] whose +[=file system locator/kind=] is {{FileSystemHandleKind/"file"}}. +A directory locator is a [=/file system locator=] whose +[=file system locator/kind=] is {{FileSystemHandleKind/"directory"}}. + +A [=/file system locator=] |a| is the same locator as +a [=/file system locator=] |b| if |a| is |b|. + +The locate an entry algorithm takes a +[=/file system locator=] |locator| and returns either a [=/file system entry=] or null. +If |locator| is a [=file locator=], this method must return either a [=file entry=] or null. +If |locator| is a [=directory locator=], this method must return either a [=directory entry=] or null. +The steps of this algorithm are [=implementation-defined=]. + +The get the locator algorithm takes a +[=/file system entry=] |entry| and returns a [=/file system locator=] |locator|. + +If |entry| is a [=file entry=], |locator| must be a [=file locator=]. +If |entry| is a [=directory entry=], |locator| must be a [=directory locator=]. +If [=locating an entry=] given [=/file system locator=] |locator| returns a +[=/file system entry=] |entry|, then [=getting the locator=] of |entry| +must return |locator| if no intermediate file system operations were run. +Typically the steps are symmetric to the [=locate an entry=] algorithm. + +If [=locating an entry=] given [=/file system locator=] |locator| returns a +[=/file system entry=] |entry|, then |entry|'s [=file system entry/name=] must +be the same [=valid file name=] as the last [=list/item=] of +|locator|'s [=file system locator/path=]. + +A file system path is a [=/list=] of one or more +[=valid file name|valid file names=]. +This may be a virtual path that is mapped to real location on disk or in memory, +may correspond directly to a path on the local file system, or may not +correspond to any file on disk at all. The actual physical location of the +corresponding [=/file system entry=] is [=implementation-defined=]. + +

Let |path| be the [=/list=] +« "`data`", "`drafts`", "`example.txt`" ». +There is no expectation that a file named `example.txt` exists anywhere on disk. ## The {{FileSystemHandle}} interface ## {#api-filesystemhandle} @@ -227,19 +232,12 @@ interface FileSystemHandle { }; -A {{FileSystemHandle}} object represents a [=/file system path=]. +A {{FileSystemHandle}} object represents a [=/file system locator=]. Each {{FileSystemHandle}} object is associated with a -path (a [=/file system path=]). +locator (a [=/file system locator=]). Note: Multiple {{FileSystemHandle}} objects can have -[=the same path as|the same=] [=path=]. - -

-To get the entry -of a given {{FileSystemHandle}} |handle|, return the result of running -[=locate=] given |handle|'s [=FileSystemHandle/path=]. - -
+[=the same locator as|the same=] [=/file system locator=].
{{FileSystemHandle}} objects are [=serializable objects=]. @@ -247,7 +245,7 @@ of a given {{FileSystemHandle}} |handle|, return the result of running Their [=serialization steps=], given |value|, |serialized| and forStorage are: 1. Set |serialized|.\[[Origin]] to |value|'s [=relevant settings object=]'s [=environment settings object/origin=]. -1. Set |serialized|.\[[Path]] to |value|'s [=FileSystemHandle/path=]. +1. Set |serialized|.\[[Locator]] to |value|'s [=FileSystemHandle/locator=].
@@ -257,7 +255,7 @@ Their [=deserialization steps=], given |serialized| and |value| are: 1. If |serialized|.\[[Origin]] is not [=same origin=] with |value|'s [=relevant settings object=]'s [=environment settings object/origin=], then [=throw=] a "{{DataCloneError}}" {{DOMException}}. -1. Set |value|'s [=FileSystemHandle/path=] to |serialized|.\[[Path]] +1. Set |value|'s [=FileSystemHandle/locator=] to |serialized|.\[[Locator]]
@@ -270,15 +268,16 @@ Their [=deserialization steps=], given |serialized| and |value| are: of a directory. : |handle| . {{FileSystemHandle/name}} - :: Returns the last path component of |handle|'s [=FileSystemHandle/path=]. + :: Returns the last path component of |handle|'s + [=FileSystemHandle/locator=]'s [=file system locator/path=].
The kind getter steps are to return -{{FileSystemHandleKind/"file"}} if [=this=] is a [=file entry=]; otherwise -{{FileSystemHandleKind/"directory"}}. +[=this=]'s [=FileSystemHandle/locator=]'s [=file system locator/kind=]. The name getter steps are to return -[=this=]'s [=FileSystemHandle/path=]'s [=file system path/name=]. +the last [=list/item=] (a [=valid file name=]) of [=this=]'s +[=FileSystemHandle/locator=]'s [=file system locator/path=]. ### The {{FileSystemHandle/isSameEntry()}} method ### {#api-filesystemhandle-issameentry} @@ -293,7 +292,8 @@ The isSameEntry(|other|) method steps are 1. Let |realm| be [=this=]'s [=relevant Realm=]. 1. Let |p| be [=a new promise=] in |realm|. 1. Run these steps [=in parallel=]: - 1. If [=this=]'s [=FileSystemHandle/path=] is [=the same path as=] |other|'s [=FileSystemHandle/path=], + 1. If [=this=]'s [=FileSystemHandle/locator=] is + [=the same locator as=] |other|'s [=FileSystemHandle/locator=], [=/resolve=] |p| with true. 1. Otherwise [=/resolve=] |p| with false. 1. Return |p|. @@ -316,15 +316,16 @@ interface FileSystemFileHandle : FileSystemHandle { }; -A {{FileSystemFileHandle}}'s associated [=FileSystemHandle/path=] -is expected to [=locate=] a [=file entry=]. +A {{FileSystemFileHandle}}'s associated [=FileSystemHandle/locator=]'s +[=file system locator/kind=] is {{FileSystemHandleKind/"file"}}.
To create a new FileSystemFileHandle given a [=file entry=] |entry| in a [=/Realm=] |realm|, run these steps: 1. Let |handle| be a [=new=] {{FileSystemFileHandle}} in |realm|. -1. Set |handle|'s [=FileSystemHandle/path=] to the result of [=getting the path=] of |entry|. +1. Set |handle|'s [=FileSystemHandle/locator=] to the result of + [=getting the locator=] of |entry|. 1. Return |handle|.
@@ -337,7 +338,7 @@ given a [=file entry=] |entry| in a [=/Realm=] |realm|, run these steps:
: file = await |fileHandle| . {{FileSystemFileHandle/getFile()}} :: Returns a {{File}} representing the state on disk of the [=file entry=] - [=locate|locatable=] by |handle|'s [=FileSystemHandle/path=]. + [=locate an entry|locatable=] by |handle|'s [=FileSystemHandle/locator=]. If the file on disk changes or is removed after this method is called, the returned {{File}} object will likely be no longer readable.
@@ -346,7 +347,8 @@ given a [=file entry=] |entry| in a [=/Realm=] |realm|, run these steps: The getFile() method steps are: 1. Let |result| be [=a new promise=]. -1. Let |entry| be the the result of [=getting the entry=] for [=this=]. +1. Let |entry| be the result of [=locating an entry=] + given [=this=]'s [=FileSystemHandle/locator=]. 1. Run these steps [=in parallel=]: 1. Let |access| be the result of running [=this=]'s [=FileSystemHandle/entry=]'s [=file system entry/query access=] given "`read`". @@ -355,8 +357,7 @@ The getFile() method steps are: 1. If |entry| is `null`, [=/reject=] |result| with a "{{NotFoundError}}" {{DOMException}} and abort. - 1. If |entry| is not a [=file entry=] [=/reject=] |result| with a - "{{TypeMismatchError}}" {{DOMException}} and abort. + 1. [=Assert=]: |entry| is a [=file entry=]. 1. Let |f| be a new {{File}}. 1. Set |f|'s snapshot state to the current state of |entry|. @@ -378,14 +379,14 @@ The getFile() method steps are: : |stream| = await |fileHandle| . {{FileSystemFileHandle/createWritable()}} : |stream| = await |fileHandle| . {{FileSystemFileHandle/createWritable()|createWritable}}({ {{FileSystemCreateWritableOptions/keepExistingData}}: true/false }) :: Returns a {{FileSystemWritableFileStream}} that can be used to write to the file. Any changes made through - |stream| won't be reflected in the [=file entry=] [=locate|locatable=] by - |fileHandle|'s [=FileSystemHandle/path=] until the stream has been closed. + |stream| won't be reflected in the [=file entry=] [=locate an entry|locatable=] by + |fileHandle|'s [=FileSystemHandle/locator=] until the stream has been closed. User agents try to ensure that no partial writes happen, i.e. the file will either contain its old contents or it will contain whatever data was written through |stream| up until the stream has been closed. This is typically implemented by writing data to a temporary file, and only replacing the - [=file entry=] [=locate|locatable=] by |fileHandle|'s [=FileSystemHandle/path=] + [=file entry=] [=locate an entry|locatable=] by |fileHandle|'s [=FileSystemHandle/locator=] with the temporary file when the writable filestream is closed. If {{FileSystemCreateWritableOptions/keepExistingData}} is false or not specified, @@ -393,7 +394,7 @@ The getFile() method steps are: otherwise the existing file is first copied to this temporary file. Creating a {{FileSystemWritableFileStream}} [=file entry/lock/take|takes a shared lock=] on the - [=file entry=] [=locate|locatable=] with |fileHandle|'s [=FileSystemHandle/path=]. + [=file entry=] [=locate an entry|locatable=] with |fileHandle|'s [=FileSystemHandle/locator=]. This prevents the creation of {{FileSystemSyncAccessHandle|FileSystemSyncAccessHandles}} for the entry, until the stream is closed. @@ -412,7 +413,8 @@ private file system=] via the {{FileSystemSyncAccessHandle}} interface. The createWritable(|options|) method steps are: 1. Let |result| be [=a new promise=]. -1. Let |entry| be the the result of [=getting the entry=] for [=this=]. +1. Let |entry| be the result of [=locating an entry=] + given [=this=]'s [=FileSystemHandle/locator=]. 1. Run these steps [=in parallel=]: 1. Let |access| be the result of running [=this=]'s [=FileSystemHandle/entry=]'s [=file system entry/request access=] given "`readwrite`". @@ -422,8 +424,7 @@ The createWritable(|options|) method 1. If |entry| is `null`, [=/reject=] |result| with a "{{NotFoundError}}" {{DOMException}} and abort. - 1. If |entry| is not a [=file entry=], [=/reject=] |result| with a - "{{TypeMismatchError}}" {{DOMException}} and abort. + 1. [=Assert=]: |entry| is a [=file entry=]. 1. Let |lockResult| be the result of [=file entry/lock/take|taking a lock=] with "`shared`" on |entry|. 1. If |lockResult| is false, [=reject=] |result| with a "{{NoModificationAllowedError}}" {{DOMException}} and abort. @@ -442,11 +443,11 @@ The createWritable(|options|) method : |handle| = await |fileHandle| . {{FileSystemFileHandle/createSyncAccessHandle()|createSyncAccessHandle}}() :: Returns a {{FileSystemSyncAccessHandle}} that can be used to read from/write to the file. Changes made through |handle| might be immediately reflected in the - [=file entry=] [=locate|locatable=] by |fileHandle|'s [=FileSystemHandle/path=]. + [=file entry=] [=locate an entry|locatable=] by |fileHandle|'s [=FileSystemHandle/locator=]. To ensure the changes are reflected in this file, the handle can be flushed. Creating a {{FileSystemSyncAccessHandle}} [=file entry/lock/take|takes an exclusive lock=] on the - [=file entry=] [=locate|locatable=] with |fileHandle|'s [=FileSystemHandle/path=]. + [=file entry=] [=locate an entry|locatable=] with |fileHandle|'s [=FileSystemHandle/locator=]. This prevents the creation of further {{FileSystemSyncAccessHandle|FileSystemSyncAccessHandles}} or {{FileSystemWritableFileStream|FileSystemWritableFileStreams}} for the entry, until the access handle is closed. @@ -462,7 +463,8 @@ The createWritable(|options|) method The createSyncAccessHandle() method steps are: 1. Let |result| be [=a new promise=]. -1. Let |entry| be the the result of [=getting the entry=] for [=this=]. +1. Let |entry| be the result of [=locating an entry=] + given [=this=]'s [=FileSystemHandle/locator=]. 1. Run these steps [=in parallel=]: 1. Let |access| be the result of running [=this=]'s [=FileSystemHandle/entry=]'s [=file system entry/request access=] given "`readwrite`". @@ -472,8 +474,7 @@ The createSyncAccessHandle() method s 1. If |entry| is `null`, [=/reject=] |result| with a "{{NotFoundError}}" {{DOMException}} and abort. - 1. If |entry| is not a [=file entry=], [=/reject=] |result| with a - "{{TypeMismatchError}}" {{DOMException}} and abort. + 1. [=Assert=]: |entry| is a [=file entry=]. 1. If |entry| does not represent a [=/file system entry=] in an [=origin private file system=], [=reject=] |result| with an "{{InvalidStateError}}" {{DOMException}} and abort. @@ -514,15 +515,16 @@ interface FileSystemDirectoryHandle : FileSystemHandle { }; -A {{FileSystemDirectoryHandle}}'s associated [=FileSystemHandle/path=] -is expected to [=locate=] a [=directory entry=]. +A {{FileSystemDirectoryHandle}}'s associated [=FileSystemHandle/locator=]'s +[=file system locator/kind=] is {{FileSystemHandleKind/"directory"}}.
To create a new FileSystemDirectoryHandle given a [=directory entry=] |entry| in a [=/Realm=] |realm|, run these steps: 1. Let |handle| be a [=new=] {{FileSystemDirectoryHandle}} in |realm|. -1. Set |handle|'s [=FileSystemHandle/path=] to the result of [=getting the path=] of |entry|. +1. Set |handle|'s [=FileSystemHandle/locator=] to the result of + [=getting the locator=] of |entry|. 1. Return |handle|.
@@ -538,7 +540,7 @@ given a [=directory entry=] |entry| in a [=/Realm=] |realm|, run these steps: : for await (let |handle| of |directoryHandle| . values()) {} : for await (let |name| of |directoryHandle| . keys()) {} :: Iterates over all entries whose parent is the [=directory entry=] - [=locate|locatable=] by |directoryHandle|'s [=FileSystemHandle/path=]. + [=locate an entry|locatable=] by |directoryHandle|'s [=FileSystemHandle/locator=]. Entries that are created or deleted while the iteration is in progress might or might not be included. No guarantees are given either way. @@ -566,11 +568,11 @@ and its async iterator |iterator|: 1. Let |promise| be [=a new promise=]. -1. Let |directory| be the the result of [=getting the entry=] for |handle|. +1. Let |directory| be the result of [=locating an entry=] + given |handle|'s [=FileSystemHandle/locator=]. 1. If |directory| is `null`, [=/reject=] |result| with a "{{NotFoundError}}" {{DOMException}} and abort. -1. If |directory| is not a [=directory entry=], [=/reject=] |result| with a - "{{TypeMismatchError}}" {{DOMException}} and abort. + 1. [=Assert=]: |directory| is a [=directory entry=]. 1. Let |access| be the result of running |handle|'s [=FileSystemHandle/entry=]'s [=file system entry/query access=] given "`read`". @@ -611,12 +613,12 @@ and its async iterator |iterator|: : |fileHandle| = await |directoryHandle| . {{FileSystemDirectoryHandle/getFileHandle()|getFileHandle}}(|name|) : |fileHandle| = await |directoryHandle| . {{FileSystemDirectoryHandle/getFileHandle()|getFileHandle}}(|name|, { {{FileSystemGetFileOptions/create}}: false }) :: Returns a handle for a file named |name| in the [=directory entry=] - [=locate|locatable=] by |directoryHandle|'s [=FileSystemHandle/path=]. + [=locate an entry|locatable=] by |directoryHandle|'s [=FileSystemHandle/locator=]. If no such file exists, this rejects. : |fileHandle| = await |directoryHandle| . {{FileSystemDirectoryHandle/getFileHandle()|getFileHandle}}(|name|, { {{FileSystemGetFileOptions/create}}: true }) :: Returns a handle for a file named |name| in the [=directory entry=] - [=locate|locatable=] by |directoryHandle|'s [=FileSystemHandle/path=]. + [=locate an entry|locatable=] by |directoryHandle|'s [=FileSystemHandle/locator=]. If no such file exists, this creates a new file. If no file with named |name| can be created this rejects. Creation can fail because there already is a directory with the same name, because the name uses characters that aren't supported in file names on the underlying file system, or @@ -633,7 +635,8 @@ The getFileHandle(|name|, |options|)getFileHandle(|name|, |options|)getFileHandle(|name|, |options|)getDirectoryHandle(|name|, |option 1. Let |result| be [=a new promise=]. 1. Let |realm| be [=this=]'s [=relevant Realm=]. -1. Let |entry| be the the result of [=getting the entry=] for [=this=]. +1. Let |entry| be the result of [=locating an entry=] + given [=this=]'s [=FileSystemHandle/locator=]. 1. Run these steps [=in parallel=]: 1. If |name| is not a [=valid file name=], [=/reject=] |result| with a {{TypeError}} and abort. @@ -720,8 +724,7 @@ The getDirectoryHandle(|name|, |option 1. If |entry| is `null`, [=/reject=] |result| with a "{{NotFoundError}}" {{DOMException}} and abort. - 1. If |entry| is not a [=directory entry=], [=/reject=] |result| with a - "{{TypeMismatchError}}" {{DOMException}} and abort. + 1. [=Assert=]: |entry| is a [=directory entry=]. 1. [=set/For each=] |child| of |entry|'s [=directory entry/children=]: 1. If |child|'s [=file system entry/name=] equals |name|: @@ -751,8 +754,8 @@ The getDirectoryHandle(|name|, |option
: await |directoryHandle| . {{FileSystemDirectoryHandle/removeEntry()|removeEntry}}(|name|) : await |directoryHandle| . {{FileSystemDirectoryHandle/removeEntry()|removeEntry}}(|name|, { {{FileSystemRemoveOptions/recursive}}: false }) - :: If the [=directory entry=] [=locate|locatable=] by |directoryHandle|'s - [=FileSystemHandle/path=] contains a file named |name|, or an empty + :: If the [=directory entry=] [=locate an entry|locatable=] by |directoryHandle|'s + [=FileSystemHandle/locator=] contains a file named |name|, or an empty directory named |name|, this will attempt to delete that file or directory. Attempting to delete a file or directory that does not exist is considered success, @@ -760,7 +763,7 @@ The getDirectoryHandle(|name|, |option : await |directoryHandle| . {{FileSystemDirectoryHandle/removeEntry()|removeEntry}}(|name|, { {{FileSystemRemoveOptions/recursive}}: true }) :: Removes the [=/file system entry=] named |name| in the [=directory entry=] - [=locate|locatable=] by |directoryHandle|'s [=FileSystemHandle/path=]. + [=locate an entry|locatable=] by |directoryHandle|'s [=FileSystemHandle/locator=]. If that entry is a directory, its contents will also be deleted recursively. Attempting to delete a file or directory that does not exist is considered success. @@ -770,7 +773,8 @@ The getDirectoryHandle(|name|, |option The removeEntry(|name|, |options|) method steps are: 1. Let |result| be [=a new promise=]. -1. Let |entry| be the the result of [=getting the entry=] for [=this=]. +1. Let |entry| be the result of [=locating an entry=] + given [=this=]'s [=FileSystemHandle/locator=]. 1. Run these steps [=in parallel=]: 1. If |name| is not a [=valid file name=], [=/reject=] |result| with a {{TypeError}} and abort. @@ -782,8 +786,7 @@ The removeEntry(|name|, |options|)
-The resolve(|possibleDescendant|) method steps are: - -1. Let |entry| be the the result of [=getting the entry=] for [=this=]. -1. Let |possibleDescendantEntry| be the the result of [=getting the entry=] for |possibleDescendant|. -1. Return the result of [=file system entry/resolving=] |possibleDescendantEntry| relative to |entry|. +The resolve(|possibleDescendant|) method steps are +to return the result of [=file system locator/resolving=] +|possibleDescendant|'s [=FileSystemHandle/locator=] +relative to [=this=]'s [=FileSystemHandle/locator=].
From 34e913af97a2fbd2c3a8f6a35f3aea7b7990f4d9 Mon Sep 17 00:00:00 2001 From: Austin Sullivan Date: Fri, 3 Mar 2023 19:09:17 +0000 Subject: [PATCH 04/12] resolve based on a locator --- index.bs | 67 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 14 deletions(-) diff --git a/index.bs b/index.bs index 2465655..19cc9c6 100644 --- a/index.bs +++ b/index.bs @@ -19,6 +19,7 @@ urlPrefix: https://tc39.es/ecma262/; spec: ECMA-262 type: dfn; text: realm; url: realm urlPrefix: https://storage.spec.whatwg.org/; spec: storage type: dfn; text: storage; url: site-storage + type: dfn; text: storage bucket; url: storage-bucket