diff --git a/index.bs b/index.bs
index 2b34491..0293c29 100644
--- a/index.bs
+++ b/index.bs
@@ -55,6 +55,12 @@ before a user has picked a location to save to, without forcing the website to u
different storage mechanism with a different API for such files. The entry point for this is the
{{StorageManager/getDirectory()|navigator.storage.getDirectory()}} method.
+It also defines an API to listen to file system change events. Without it, sites
+can recursively poll the file system to find changes in the files or folder
+structure. This can be time consuming especially for large directories. The
+{{FileSystemObserver}} provides an API to listen for change events so that
+polling for them isn't required.
+
# Files and Directories # {#files-and-directories}
@@ -62,9 +68,8 @@ different storage mechanism with a different API for such files. The entry point
### File System ### {#concept-file-system}
-A file system is an [=implementation-defined=]
-[=storage endpoint=] that maintains a mapping of [=file system path=]s to
-[=file system entry|file system entries=].
+A file system maintains an [=implementation-defined=] mapping
+ of [=file system path=]s to [=file system entries=].
Each [=/file system=] has an associated root,
an opaque [=string=] whose value is [=implementation-defined=].
@@ -83,7 +88,7 @@ A [=/file system path=] |a| is the same path as
Each [=/file system=] has an associated
@@ -111,12 +116,273 @@ return value |path| must adhere to these constraints:
+A file system event is a [=struct=] consisting of a
+type (a
+{{FileSystemChangeType}}), an
+entry type (a
+{{FileSystemHandleKind}} or null), a
+modified path (a
+[=/file system path=]), and a
+from path (a
+[=/file system path=] or null).
+
+Note: A [=/file system=] fires these events in response to file operations.
+
+The [=file system/file system event/from path=] must be set when
+[=file system/file system event/type=] is "{{FileSystemChangeType/moved}}" and
+must be null otherwise.
+
+Note: The [=file system/file system event/entry type=] is null when the
+[=/file system=] cannot determine the {{FileSystemHandleKind}} of the
+[=file system/file system event/modified path=] due to the underlying
+[=file system entry=] no longer being there.
+
+A [=/file system=] has an associated [=/set=] of
+[=file system observer registrations=]
+observer registrations which is initialized to the
+empty set.
+
+When a user agent receives a [=/list=] of [=file system/file system events=]
+|events| for a [=/file system=] |fileSystem|, the user agent MUST
+[=file system/notify observer registrations=] of the |fileSystem| of |events|.
+
+Note: The [=file system/file system events=] fired by a [=/file system=] may be
+unreliable and can be inaccurate, out of order, or missing.
+
+
+To notify observer registrations of a [=/file system=]
+|fileSystem| of a [=/list=] of [=file system/file system events=] |events|:
+
+1. [=Enqueue the following steps=] to the [=file system queue=]:
+ 1. [=list/For each=] |observerRegistration| of the |fileSystem|'s
+ [=file system/observer registrations=].
+ 1. [=file system observer registration/Notify=] |observerRegistration| of |events|
+ from |fileSystem|.
+
+
+
+When a user agent receives an error event for a [=/file system=] |fileSystem|
+and |observerRegistrations| (a [=subset=] of the |fileSystem|'s
+[=file system/observer registrations=]), the user agent MUST
+[=file system/send an error|send the error=] to |observerRegistrations| of |fileSystem|.
+
+
+To
send an error to a [=/set=] of
+[=file system observer registrations=] |observerRegistrations| of a
+[=/file system=] |fileSystem|:
+
+1. [=Enqueue the following steps=] to the [=file system queue=]:
+ 1. [=Assert=] |observerRegistrations| is a [=subset=] of |fileSystem|'s
+ [=file system/observer registrations=].
+ 1. [=list/For each=] |observerRegistration| of |observerRegistrations|:
+ 1. [=file system observer registration/Destroy=] |observerRegistration|.
+ 1. Let |observer| be |observerRegistration|'s
+ [=file system observer registration/observer=].
+ 1. Let |global| be |observer|'s [=relevant global object=].
+ 1. [=Queue a storage task=] with |global| to run these steps:
+ 1. Let |changedHandle| be the |observerRegistration|'s
+ [=file system observer registration/root handle=].
+ 1. Let |record| be the result of
+
creating a new `FileSystemChangeRecord` for
+ |observerRegistration| given |changedHandle|,
+ "{{FileSystemChangeType/errored}}", and null.
+
+ 1. Invoke |observer|'s [=FileSystemObserver/callback=] with «|record|» as
+ the first argument and |observer| as the second argument.
+
+
+
+
+
+A file system observer registration consists of a
+{{FileSystemObserver}}
+observer, a
+{{FileSystemHandle}}
+root handle, and a
+[=/boolean=] recursive.
+
+
+To create an observer registration
+for {{FileSystemObserver}} |observer| on {{FileSystemHandle}} |rootHandle| with
+[=/boolean=] |recursive|:
+
+
+1. Let |observerRegistration| be a [=file system observer registration=] whose
+ [=file system observer registration/observer=] is |observer|,
+ [=file system observer registration/root handle=] is |rootHandle|, and
+ [=file system observer registration/recursive=] is |recursive|.
+
+1. Let |observerRegistrationLocator| be |rootHandle|'s [=FileSystemHandle/locator=].
+1. Let |observerRegistrationMap| be |observer|'s [=FileSystemObserver/observerRegistrations=].
+1. Let |fileSystem| be the |observerRegistrationLocator|'s
+ [=file system locator/file system=].
+
+1. [=list/Append=] |observerRegistration| to the |fileSystem|'s
+ [=file system/observer registrations=].
+1. [=map/set=] |observerRegistrationMap|[|observerRegistrationLocator|] to |observerRegistration|.
+
+Note: These steps have to be run on the [=file system queue=].
+
+
+
+
+To destroy
+[=file system observer registration=] |observerRegistration|:
+
+1. Let |observer| be |observerRegistration|'s [=file system observer registration/observer=].
+1. Let |rootHandle| be |observerRegistration|'s [=file system observer registration/root handle=].
+1. Let |observerRegistrationLocator| be |rootHandle|'s [=FileSystemHandle/locator=].
+1. Let |fileSystem| be |observerRegistrationLocator|'s
+ [=file system locator/file system=].
+1. [=list/Remove=] |observerRegistration| from the |fileSystem|'s
+ [=file system/observer registrations=].
+1. [=map/Remove=] |observerRegistrationLocator| from |observer|'s
+ [=FileSystemObserver/observerRegistrations=].
+
+Note: These steps have to be run on the [=file system queue=].
+
+
+
+
+To
notify a
+[=file system observer registration=] |observerRegistration| of a [=/list=] of
+[=file system/file system events=] |events| from a [=/file system=]
+|fileSystem|:
+
+1. Let |rootHandle| be |observerRegistration|'s [=file system observer registration/root handle=].
+1. Let |observerRegistrationLocator| be |rootHandle|'s [=FileSystemHandle/locator=].
+
+1. [=Assert=]: |observerRegistrationLocator|'s [=file system locator/file system=] is equal to
+ |fileSystem|.
+
+1. Let |realm| be |rootHandle|'s [=relevant realm=].
+
+1. Let |observer| be |observerRegistration|'s [=file system observer registration/observer=].
+1. Let |global| be |observer|'s [=relevant global object=].
+1. [=Queue a storage task=] with |global| to run these steps:
+ 1. Let |records| be a [=/list=] of {{FileSystemChangeRecord}}.
+ 1. [=list/For each=] |event| of |events|:
+
+ 1. Let |eventType| be |event|'s [=file system/file system event/type=].
+
+ 1. [=Assert=] |eventType| is not equal to
+ "{{FileSystemChangeType/errored}}".
+
+ Note: "{{FileSystemChangeType/errored}}" events are sent in the
+ [=file system/send an error=] steps.
+
+ 1. Let |eventEntryType| be |event|'s [=file system/file system event/entry type=].
+
+ 1. If |eventType| is "{{FileSystemChangeType/modified}}" and
+ |eventEntryType| is
+ "{{FileSystemHandleKind/directory}}" or null, [=continue=].
+
+ Note: We can safely ignore "{{FileSystemChangeType/modified}}" events for
+ "{{FileSystemHandleKind/directory}}". These might be sent when one of its
+ children receives an event which the page will be made aware of through
+ that child event. Or they might be sent when some OS specific property
+ changes which the web page cannot observe through web APIs. Similarly when
+ we don't know the {{FileSystemHandleKind}}, we can ignore it since the
+ [=/file system entry=] at the
+ [=file system/file system event/modified path=] no longer exists.
+
+ 1. If |eventEntryType| is null:
+ 1. Set |eventEntryType| to |observerRegistrationLocator|'s
+ [=file system locator/kind=].
+
+ Note: When we don't know the {{FileSystemHandleKind}} of the
+ [=file system/file system event/modified path=], we have to arbitrarily
+ choose one to construct the {{FileSystemChangeRecord/changedHandle}}.
+ Setting it to |observerRegistrationLocator|'s [=file system locator/kind=]
+ atleast means it'll be right for events on the root handle.
+
+ 1. Let |modifiedPath| be |event|'s [=file system/file system event/modified path=].
+ 1. Let |fromPath| be |event|'s [=file system/file system event/from path=].
+
+ 1. Let |changedHandle| be the result of
+
creating a new `FileSystemHandle` given |fileSystem|,
+ |modifiedPath|, and |eventEntryType| in |realm|.
+ 1. Let |movedFromHandle| be null.
+
+ 1. Let |modifiedPathInScope| be equal to |changedHandle|
+ [=file system observer registration/is in scope=] of |observerRegistration|.
+ 1. Let |fromPathInScope| be false.
+
+ 1. If |eventType| is "{{FileSystemChangeType/moved}}":
+ 1. [=Assert=]: |fromPath| is not null.
+ 1. Set |movedFromHandle| to the result of
+
creating a new `FileSystemHandle` given |fileSystem|,
+ |fromPath|, and |eventEntryType| in |realm|.
+ 1. Set |fromPathInScope| equal to |movedFromHandle|
+ [=file system observer registration/is in scope=] of |observerRegistration|.
+
+ 1. If both |modifiedPathInScope| and |fromPathInScope| are false, [=continue=].
+
+ 1. If |eventType| is "{{FileSystemChangeType/moved}}":
+ 1. If |modifiedPathInScope| is false:
+ 1. Set |eventType| to "{{FileSystemChangeType/disappeared}}".
+ 1. Set |changedHandle| to |movedFromHandle|.
+ 1. Set |fromPath| to null.
+ 1. If |fromPathInScope| is false:
+ 1. Set |eventType| to "{{FileSystemChangeType/appeared}}".
+ 1. Set |fromPath| to null.
+
+ Note: Some [=/file systems=] convert "{{FileSystemChangeType/moved}}" events
+ in and out of scope to "{{FileSystemChangeType/appeared}}" and
+ "{{FileSystemChangeType/disappeared}}" respectively before we can. So to
+ maintain consistency, we do it here.
+
+ 1. Let |record| be the result of
creating a new `FileSystemChangeRecord` for
+ |observerRegistration| given |changedHandle|, |eventType|, and |fromPath|.
+ 1. [=list/Append=] |record| to |records|.
+
+ 1. If |eventType| is equal to "{{FileSystemChangeType/disappeared}}" and
+ |changedHandle|'s [=FileSystemHandle/locator=] is equal to
+ |observerRegistrationLocator|:
+ 1. Set |errorRecord| to the result of
+
creating a new `FileSystemChangeRecord` for |observerRegistration| given
+ |changedHandle|, "{{FileSystemChangeType/errored}}", and null.
+ 1. [=list/Append=] |errorRecord| to |records|.
+ 1. [=file system observer registration/Destroy=] |observerRegistration|.
+ 1. [=break=].
+
+ 1. If |records| is not [=set/is empty|empty=]:
+ 1. Invoke |observer|'s [=FileSystemObserver/callback=] with |records| as the
+ first argument and |observer| as the second argument.
+
+Note: These steps have to be run on the [=file system queue=].
+
+
+
+
+To determine if a {{FileSystemHandle}} |handle|
+is in scope of a
+[=file system observer registration=] |observerRegistration|:
+
+
+1. Let |observerRegistrationLocator| be |observerRegistration|'s [=file system observer registration/root handle=]'s
+ [=FileSystemHandle/locator=].
+1. Let |observerRegistrationRecursive| be |observerRegistration|'s [=file system observer registration/recursive=].
+1. Let |handleLocator| be |handle|'s [=FileSystemHandle/locator=].
+
+1. Let |pathRelation| be the result of [=file system locator/getting the relationship=]
+ between |observerRegistrationLocator| and |handleLocator|.
+
+1. If |pathRelation| is "`other`" or "`ancestor`", return false.
+1. If |pathRelation| is "`descendant`" and |observerRegistrationRecursive| is false,
+ return false.
+1. Return true.
+
+Note: These steps have to be run on the [=file system queue=].
+
+
+
### File System Entry ### {#concept-file-system-entry}
A file system entry is either a [=file entry=] or a [=directory entry=].
-Each [=/file system entry=] has an associated
-file system (a [=/file system=]).
+Each [=/file system entry=] has an associated [=/file system=]
+file system.
Each [=/file system entry=] has an associated
query access
@@ -290,34 +556,49 @@ a [=/file system locator=] |b| if
To resolve a
-[=/file system locator=] |child| relative to a [=directory locator=] |root|:
+[=/file system locator=] |child| relative to a [=file system locator=] |root|:
-1. Let |result| be [=a new promise=].
-1. [=Enqueue the following steps=] to the [=file system queue=]:
- 1. If |child|'s [=FileSystemHandle/locator=]'s [=file system locator/file system=]
- is not |root|'s [=FileSystemHandle/locator=]'s [=file system locator/file system=],
- [=/resolve=] |result| with null, and abort these steps.
+1. Let |relationship| be the result of [=file system locator/getting the relationship=]
+ between |root| and |child|.
+1. If |relationship| is equal to "`other`" or "`ancestor`", return null.
+1. If |relationship| is equal to "`self`", return « ».
- 1. Let |childPath| be |child|'s [=FileSystemHandle/locator=]'s [=file system locator/path=].
- 1. Let |rootPath| be |root|'s [=FileSystemHandle/locator=]'s [=file system locator/path=].
- 1. If |childPath| is [=the same path as=] |rootPath|,
- [=/resolve=] |result| with « », and abort these steps.
+1. Let |childPath| be |child|'s [=file system locator/path=].
+1. Let |rootPath| be |root|'s [=file system locator/path=].
- 1. If |rootPath|'s [=list/size=] is greater than |childPath|'s [=list/size=],
- [=/resolve=] |result| with null, and abort these steps.
+1. Let |relativePath| be « ».
+1. [=list/For each=] |index| of [=the range=] from |rootPath|'s [=list/size=]
+ to |childPath|'s [=list/size=], exclusive,
+ [=list/append=] |childPath|[|index|] to |relativePath|.
- 1. [=list/For each=] |index| of |rootPath|'s [=list/indices=]:
- 1. If |rootPath|.\[[|index|]] is not |childPath|.\[[|index|]], then
- [=/resolve=] |result| with null, and abort these steps.
+1. Return |relativePath|.
- 1. Let |relativePath| be « ».
- 1. [=list/For each=] |index| of [=the range=] from |rootPath|'s [=list/size=]
- to |rootPath|'s [=list/size=], exclusive,
- [=list/append=] |childPath|.\[[|index|]] to |relativePath|.
+Note: These steps have to be run on the [=file system queue=].
- 1. [=/Resolve=] |result| with |relativePath|.
+
-1. Return |result|.
+
+To get the relationship from a
+[=/file system locator=] |self| to a [=file system locator=] |related|:
+
+1. If |self|'s [=file system locator/file system=] is not |related|'s
+ [=file system locator/file system=], return "`other`".
+
+1. Let |selfPath| be |self|'s [=file system locator/path=].
+1. Let |relatedPath| be |related|'s [=file system locator/path=].
+
+1. Let |selfPathSize| be |selfPath|'s [=list/size=].
+1. Let |relatedPathSize| be |relatedPath|'s [=list/size=].
+
+1. [=list/For each=] |index| of |selfPath|'s [=list/indices=]:
+ 1. If |index| is greater than or equal to |relatedPathSize|, return "`ancestor`".
+ 1. If |selfPath|[|index|] is not |relatedPath|[|index|], return "`other`".
+
+1. If |selfPathSize| equals |relatedPathSize|, return "`self`".
+1. If |selfPathSize| + 1 equals |relatedPathSize|, return "`direct child`".
+1. Return "`descendant`".
+
+Note: These steps have to be run on the [=file system queue=].
@@ -330,8 +611,6 @@ The locate an entry algorithm give
1. Let |entry| be the result of running |fileSystem|'s
[=file system/locate an entry=] given |path|.
1. If |entry| is null, return null.
-1. If |locator| is a [=file locator=], [=Assert=]: |entry| is a [=file entry=].
-1. If |locator| is a [=directory locator=], [=Assert=]: |entry| is a [=directory entry=].
1. Return |entry|.
@@ -380,6 +659,20 @@ A {{FileSystemHandle}} object is associated with a
+To create a new `FileSystemHandle` given a
+[=/file system=] |fileSystem|, a [=/file system path=] |path|, and a
+{{FileSystemHandleKind}} |kind| in a [=/Realm=] |realm|:
+
+1. If |kind| is "`file`":
+ 1. Set |changedHandle| to the result of creating a new `FileSystemFileHandle`
+ given |fileSystem| and |path| in |realm|.
+1. Otherwise:
+ 1. Set |changedHandle| to the result of creating a new `FileSystemDirectoryHandle`
+ given |fileSystem| and |path| in |realm|.
+
+
+
A {{FileSystemHandle}}
is in a bucket file system
if the first [=list/item=] of its [=FileSystemHandle/locator=]'s
@@ -481,7 +774,7 @@ given a [=directory locator=] |parentLocator| and a string |name| in a [=/Realm=
1. Let |handle| be a [=new=] {{FileSystemFileHandle}} in |realm|.
1. Let |childType| be "{{FileSystemHandleKind/file}}".
-1. Let |childFileSystem| be the |parentLocator|'s [=file system locator/file system=]
+1. Let |childFileSystem| be the |parentLocator|'s [=file system locator/file system=].
1. Let |childPath| be the result of [=list/clone|cloning=] |parentLocator|'s
[=file system locator/path=] and [=list/append|appending=] |name|.
1. Set |handle|'s [=FileSystemHandle/locator=] to a [=/file system locator=] whose
@@ -1123,10 +1416,18 @@ if (relative_path === null) {
-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=].
+The resolve(|possibleDescendant|)
+method steps are:
+
+1. Let |result| be [=a new promise=].
+1. Let |global| be [=this=]'s [=relevant global object=].
+1. [=Enqueue the following steps=] to the [=file system queue=]:
+ 1. Let |relativePath| be the result of [=file system locator/resolving=]
+ |possibleDescendant|'s [=FileSystemHandle/locator=]
+ relative to [=this=]'s [=FileSystemHandle/locator=].
+ 1. [=Queue a storage task=] with |global| to run these steps:
+ 1. [=/resolve=] |result| with |relativePath|.
+1. Return |result|.
@@ -1713,14 +2014,15 @@ guarantee.
# Accessing the Bucket File System # {#sandboxed-filesystem}
-The bucket file system
-is a [=/file system=] implementation
-whose [=file system/root=] is an [=implementation-defined=] opaque [=string=]
-and whose [=storage endpoint=]'s
-identifier of `"fileSystem"`,
+The bucket file system is a
+[=storage endpoint=] whose
+identifier is `"fileSystem"`,
types are `« "local" »`,
and quota is null.
+The [=/bucket file system=] implements [=/file system=] with
+[=file system/root=] as an [=implementation-defined=] opaque [=string=].
+
Note: [=/bucket file system=]'s [=file system/root=] might include relevant
identifying information such as the [=storage bucket=].
@@ -1776,6 +2078,197 @@ The getDirectory() method steps are:
+# Observing file system change events # {#observing-the-file-system}
+
+## The {{FileSystemObserver}} interface ## {#api-filesystemobserver}
+
+
+dictionary FileSystemObserverObserveOptions {
+ boolean recursive = false;
+};
+
+callback FileSystemObserverCallback = undefined (
+ sequence records,
+ FileSystemObserver observer
+);
+
+[
+ Exposed=(DedicatedWorker,SharedWorker,Window),
+ SecureContext
+] interface FileSystemObserver {
+ constructor(FileSystemObserverCallback callback);
+
+ Promise observe(FileSystemHandle handle,
+ optional FileSystemObserverObserveOptions options = {});
+ undefined unobserve(FileSystemHandle handle);
+ undefined disconnect();
+};
+
+
+
+ The {{FileSystemObserver}} interface can be used to observe
+ [=file system/file system events=].
+
+
+The {{FileSystemObserver}} has an asociated {{FileSystemObserverCallback}}
+callback.
+
+The {{FileSystemObserver}} has an associated
+observerRegistrations (a [=map=] of
+[=/file system locators=] to [=file system observer registrations=]).
+
+### The {{FileSystemObserver}} constructor ### {#api-filesystemobsever-constructor}
+
+
+The new FileSystemObserver(FileSystemObserverCallback |callback|)
+steps are:
+
+1. Let [=this=] be a new {{FileSystemObserver}}.
+1. Set [=this=]'s [=FileSystemObserver/callback=] to |callback|.
+1. Set [=this=]'s [=FileSystemObserver/observerRegistrations=] be the empty map.
+
+
+
+### The {{FileSystemObserver/observe()}} method ### {#api-filesystemobserver-observe}
+
+
+
+The observe(FileSystemHandle |handle|,
+FileSystemObserverObserveOptions |options|) steps are:
+
+1. Let |result| be [=a new promise=].
+
+1. Let |recursive| be |options|["{{FileSystemObserverObserveOptions/recursive}}"].
+1. Let |observerRegistrationMap| be [=this=]'s [=FileSystemObserver/observerRegistrations=].
+1. Let |locator| be |handle|'s [=FileSystemHandle/locator=].
+1. Let |global| be [=this=]'s [=relevant global object=].
+
+1. [=Enqueue the following steps=] to the [=file system queue=]:
+ 1. If |observerRegistrationMap|[|locator|] [=map/exists=], 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/query access=] given "`read`".
+
+ 1. [=Queue a storage task=] with |global| to run these steps:
+ 1. If |accessResult|'s [=file system access result/permission state=]
+ is not "{{PermissionState/granted}}", [=/reject=] |result| with a
+ {{DOMException}} of |accessResult|'s
+ [=file system access result/error name=] and abort these steps.
+
+ 1. If |entry| is null, [=/reject=] |result| with a
+ "{{NotFoundError}}" {{DOMException}} and abort these steps.
+ 1. [=Assert=]: |entry| is a [=file entry=].
+
+ 1. [=Enqueue the following steps=] to the [=file system queue=]:
+ 1. [=file system observer registration/Create an observer registration=]
+ for [=this=] on |handle| with |recursive|.
+
+ 1. [=/Resolve=] |result| with null.
+
+
+
+
+### The {{FileSystemObserver/unobserve()}} method ### {#api-filesystemobserver-unobserve}
+
+
+The unobserve(FileSystemHandle |handle|)
+steps are:
+
+1. Let |locator| be |handle|'s [=FileSystemHandle/locator=].
+1. Let |observerRegistrationMap| be [=this=]'s [=FileSystemObserver/observerRegistrations=].
+
+1. [=Enqueue the following steps=] to the [=file system queue=]:
+ 1. If |observerRegistrationMap|[|locator|] does not [=map/exist=], abort these steps.
+ 1. [=file system observer registration/Destroy=] |observerRegistrationMap|[|locator|].
+
+
+
+### The {{FileSystemObserver/disconnect()}} method ### {#api-filesystemobserver-disconnect}
+
+
+The disconnect() steps are:
+
+1. Let |observerRegistrationMap| be [=this=]'s [=FileSystemObserver/observerRegistrations=].
+
+1. [=Enqueue the following steps=] to the [=file system queue=]:
+ 1. Let |observerRegistrations| be the result of [=map/getting the values=] of
+ |observerRegistrationMap|.
+ 1. [=list/For each=] |observerRegistration| in |observerRegistrations|:
+ 1. [=file system observer registration/Destroy=] |observerRegistration|.
+
+
+
+## The {{FileSystemChangeRecord}} interface ## {#api-filesystemchangerecord}
+
+
+enum FileSystemChangeType {
+ "appeared",
+ "disappeared",
+ "errored",
+ "modified",
+ "moved",
+ "unknown",
+};
+
+dictionary FileSystemChangeRecord {
+ FileSystemHandle root;
+ FileSystemHandle changedHandle;
+ FrozenArray relativePathComponents;
+ FileSystemChangeType type;
+ FrozenArray? relativePathMovedFrom;
+};
+
+
+
+ : root
+ :: The handle that was passed to FileSystemObserver.observe().
+ : changedHandle
+ :: The path of `changedHandle` relative to `root`.
+ : relativePathComponents
+ :: The path of {{FileSystemChangeRecord/changedHandle}} relative to
+ {{FileSystemChangeRecord/root}}.
+ : type
+ :: The type of change.
+ : relativePathMovedFrom
+ :: If {{FileSystemChangeRecord/type}} is "{{FileSystemChangeType/moved}}",
+ this corresponds to the former path of {{FileSystemChangeRecord/changedHandle}}
+ relative to {{FileSystemChangeRecord/root}}, if the former path is known;
+ otherwise null.
+
+
+
+
+To
+create a new `FileSystemChangeRecord`
+for a [=file system observer registration=] |observerRegistration| given a {{FileSystemHandle}}
+|changedHandle|, a {{FileSystemChangeType}} |type|, and an optional
+[=/file system locator=] |movedFromPath|:
+
+1. Let |root| be |observerRegistration|'s
+ [=file system observer registration/root handle=].
+1. Let |rootLocator| be |root|'s [=FileSystemHandle/locator=].
+1. Let |changedHandleLocator| be |changedHandle|'s [=FileSystemHandle/locator=].
+1. Let |relativePathComponents| be the result of [=file system locator/resolving=]
+ |changedHandleLocator| relative to |rootLocator|.
+1. Let |relativePathMovedFrom| be null.
+1. If |movedFromPath| was given, set |relativePathMovedFrom| to the result of
+ [=file system locator/resolving=] |movedFromPath| relative to |rootLocator|.
+
+
+1. Let |realm| be |changedHandle|'s [=relevant realm=].
+1. Let |record| be a [=new=] {{FileSystemChangeRecord}} in |realm|.
+
+1. Set |record|'s {{FileSystemChangeRecord/root}} to |root|.
+1. Set |record|'s {{FileSystemChangeRecord/changedHandle}} to |changedHandle|.
+1. Set |record|'s {{FileSystemChangeRecord/relativePathComponents}} to |relativePathComponents|.
+1. Set |record|'s {{FileSystemChangeRecord/type}} to |type|.
+1. Set |record|'s {{FileSystemChangeRecord/relativePathMovedFrom}} to |relativePathMovedFrom|.
+
+1. Return |record|.
+
+
+
Acknowledgments