diff --git a/index.bs b/index.bs
index 881fb19..3202fbd 100644
--- a/index.bs
+++ b/index.bs
@@ -110,7 +110,10 @@ specifications do not need to bother implementing [=/file system entry=]'s
Issue(101): Make access check algorithms associated with a FileSystemHandle.
-Each [=/file system entry=] has an associated name (a [=string=]).
+Each [=/file system entry=] has an associated name (a [=string=]),
+a lock (a string that may exclusively be "`open`", "`taken-exclusive`" or "`taken-shared`")
+and a lock count
+(a number representing the number of locks that are taken at a given point in time).
A valid file name is a [=string=] that is not an empty string, is not equal to "." or "..",
and does not contain '/' or any other character used as path separator on the underlying platform.
@@ -124,50 +127,83 @@ Issue: We should consider having further normative restrictions on file names th
never be allowed using this API, rather than leaving it entirely up to underlying file
systems.
-A file entry additionally consists of
-binary data (a [=byte sequence=]), a
-modification timestamp (a number representing the number of milliseconds since the Unix Epoch),
-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).
-
A user agent has an associated file system queue which is the
result of [=starting a new parallel queue=]. This queue is to be used for all
file system operations.
-To take a [=file entry/lock=] with a |value| of
-"`exclusive`" or "`shared`" on a given [=file entry=] |file|:
-
-1. Let |lock| be the |file|'s [=file entry/lock=].
-1. Let |count| be the |file|'s [=file entry/shared lock count=].
+To take a lock with a |value| of
+"`exclusive`" or "`shared`" on a given [=/file system entry=] |entry|:
+
+1. Let |lock| be the |entry|'s [=file system entry/lock=].
+1. Let |count| be the |entry|'s [=file system entry/lock count=].
+1. Let |ancestorLockStatus| be the result of [=file system entry/checking for an ancestor lock=] on |entry|.
+1. If |ancestorLockStatus| is "`taken`":
+ 1. Return "`failure`".
+1. If |entry| is a [=directory entry=]:
+ 1. Let |descendantLockStatus| be the result of [=file system entry/checking for a descendant lock=] on |entry|.
+ 1. If |descendantLockStatus| is "`taken`":
+ 1. Return "`failure`".
+1. If |value| is "`exclusive`" or |lock| is "`taken-exclusive`":
+ 1. Return "`failure`".
1. If |value| is "`exclusive`":
- 1. If |lock| is "`open`":
- 1. Set lock to "`taken-exclusive`".
- 1. Return "`success`".
-1. If |value| is "`shared`":
- 1. If |lock| is "`open`":
- 1. Set |lock| to "`taken-shared`".
- 1. Set |count| to 1.
- 1. Return "`success`".
- 1. Otherwise, if |lock| is "`taken-shared`":
- 1. Increase |count| by 1.
- 1. Return "`success`".
-1. Return "`failure`".
+ 1. [=Assert=]: |lock| is "`open`".
+ 1. [=Assert=]: |count| is 0.
+ 1. Set lock to "`taken-exclusive`".
+1. Otherwise:
+ 1. [=Assert=]: |lock| is not "`taken-exclusive`".
+ 1. Set lock to "`taken-shared`".
+1. Increase |count| by 1.
+1. Return "`success`".
Note: These steps have to be run on the [=file system queue=].
-To release a [=file entry/lock=] on a given
-[=file entry=] |file|:
+To check for an ancestor lock on a given
+[=/file system entry=] |entry|:
+
+1. Let |parent| be the |entry|'s [=file system entry/parent=].
+1. If |parent| is null:
+ 1. Return "`open`".
+1. Let |lock| be the |parent|'s [=file system entry/lock=].
+1. If |lock| is not "`open`":
+ 1. Return "`taken`".
+1. Let |ancestorLockStatus| be the result of [=file system entry/checking for an ancestor lock=] on |parent|.
+1. Return |ancestorLockStatus|.
-1. Let |lock| be the |file|'s associated [=file entry/lock=].
-1. Let |count| be the |file|'s [=file entry/shared lock count=].
-1. If |lock| is "`taken-shared`":
- 1. Decrease |count| by 1.
- 1. If |count| is 0, set |lock| to "`open`".
-1. Otherwise, set |lock| to "`open`".
+Note: These steps have to be run on the [=file system queue=].
+
+
+
+
+To check for a descendant lock on a given
+[=directory entry=] |directory|:
+
+1. [=set/For each=] |child| of |directory|'s [=directory entry/children=]:
+ 1. Let |lock| be the |child|'s [=file system entry/lock=].
+ 1. If |lock| is not "`open`":
+ 1. Return "`taken`".
+ 1. If |child| is a [=directory entry=]:
+ 1. Let |descendantLockStatus| be the result of [=file system entry/checking for a descendant lock=] on |child|.
+ 1. If |descendantLockStatus| is "`taken`":
+ 1. Return "`taken`".
+1. Return "`open`".
+
+Note: These steps have to be run on the [=file system queue=].
+
+
+
+
+To
release a [=file system entry/lock=] on a given
+[=/file system entry=] |entry|:
+
+1. Let |lock| be the |entry|'s associated [=file system entry/lock=].
+1. [=Assert=]: |lock| is not "`open`".
+1. Let |count| be the |entry|'s [=file system entry/lock count=].
+1. Decrease |count| by 1.
+1. If |count| is 0, set |lock| to "`open`".
Note: These steps have to be run on the [=file system queue=].
@@ -176,6 +212,10 @@ Note: These steps have to be run on the [=file system queue=].
Note: Locks help prevent concurrent modifications to a file. A {{FileSystemWritableFileStream}}
requires a shared lock, while a {{FileSystemSyncAccessHandle}} requires an exclusive one.
+A
file entry additionally consists of
+
binary data (a [=byte sequence=]) and a
+
modification timestamp (a number representing the number of milliseconds since the
Unix Epoch).
+
A
directory entry additionally consists of a [=/set=] of
children, which are themselves [=/file system entries=].
Each member is either a [=/file entry=] or a [=/directory entry=].
@@ -538,7 +578,7 @@ The
getFile() method steps are:
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
+ Creating a {{FileSystemWritableFileStream}} [=file system entry/take a lock|takes a shared lock=] on the
[=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.
@@ -575,7 +615,7 @@ The
createWritable(|options|) method
|result| with a "{{NotFoundError}}" {{DOMException}} and abort these steps.
1. [=Assert=]: |entry| is a [=file entry=].
- 1. Let |lockResult| be the result of [=file entry/lock/take|taking a lock=]
+ 1. Let |lockResult| be the result of [=file system entry/take a lock|taking a lock=]
with "`shared`" on |entry|.
1. [=Queue a storage task=] with |global| to run these steps:
@@ -603,7 +643,7 @@ The
createWritable(|options|) method
[=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
+ Creating a {{FileSystemSyncAccessHandle}} [=file system entry/take a lock|takes an exclusive lock=] on the
[=file entry=] [=locate an entry|locatable=] with |fileHandle|'s [=FileSystemHandle/locator=].
This prevents the creation of further {{FileSystemSyncAccessHandle|FileSystemSyncAccessHandles}}
or {{FileSystemWritableFileStream|FileSystemWritableFileStreams}}
@@ -645,7 +685,7 @@ The
createSyncAccessHandle() method s
|result| with a "{{NotFoundError}}" {{DOMException}} and abort these steps.
1. [=Assert=]: |entry| is a [=file entry=].
- 1. Let |lockResult| be the result of [=file entry/lock/take|taking a lock=]
+ 1. Let |lockResult| be the result of [=file system entry/take a lock|taking a lock=]
with "`exclusive`" on |entry|.
1. [=Queue a storage task=] with |global| to run these steps:
@@ -1181,7 +1221,7 @@ given a [=file entry=] |file| in a [=/Realm=] |realm|:
file on disk being written to.
1. [=Enqueue the following steps=] to the [=file system queue=]:
- 1. [=file entry/lock/release|Release the lock=] on
+ 1. [=file system entry/lock/release|Release the lock=] on
|stream|'s [=FileSystemWritableFileStream/[[file]]=].
1. [=Queue a storage task=] with |file|'s [=relevant global object=]
to [=/resolve=] |closeResult| with `undefined`.
@@ -1189,7 +1229,7 @@ given a [=file entry=] |file| in a [=/Realm=] |realm|:
1. Return |closeResult|.
1. Let |abortAlgorithm| be these steps:
1. [=enqueue steps|Enqueue this step=] to the [=file system queue=]:
- 1. [=file entry/lock/release|Release the lock=] on
+ 1. [=file system entry/lock/release|Release the lock=] on
|stream|'s [=FileSystemWritableFileStream/[[file]]=].
1. Let |highWaterMark| be 1.
1. Let |sizeAlgorithm| be an algorithm that returns `1`.
@@ -1649,7 +1689,7 @@ The
flush() method steps are:
: |handle| . {{FileSystemSyncAccessHandle/close()}}
:: Closes the access handle or no-ops if the access handle is already closed.
This disables any further operations on it and
- [=file entry/lock/release|releases the lock=] on the
+ [=file system entry/lock/release|releases the lock=] on the
[=FileSystemSyncAccessHandle/[[file]]=] associated with |handle|.
@@ -1661,7 +1701,7 @@ The close() method steps are:
1. Set |lockReleased| to false.
1. Let |file| be [=this=]'s [=FileSystemSyncAccessHandle/[[file]]=].
1. [=Enqueue the following steps=] to the [=file system queue=]:
- 1. [=file entry/lock/release|Release the lock=] on |file|.
+ 1. [=file system entry/lock/release|Release the lock=] on |file|.
1. Set |lockReleased| to true.
1. [=Pause=] until |lockReleased| is true.