diff --git a/index.bs b/index.bs
index 881fb19..8e81aec 100644
--- a/index.bs
+++ b/index.bs
@@ -124,50 +124,97 @@ 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 lock type is a [=string=] that may exclusively be "`open`",
+"`exclusive`", or "`shared`".
+
+A file lock is a [=struct=] with the following [=struct/items=]:
+
+: type
+:: A [=lock type=].
+: globals
+:: A [=/list=] of [=realm/global objects=] representing the current holders of the lock.
+
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 lock (a [=file lock=]), a pending lock (a [=file lock=]),
+and pending steps (a [=/list=] of sets of steps).
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
release a [=file entry/lock=] on a given
-[=file entry=] |file|:
+[=/file entry=] |file| with a [=realm/global object=] |global|:
-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`".
+1. Let |lock| be the |file|'s [=file entry/lock=].
+1. Let |lockGlobals| be the |lock|'s [=file lock/globals=].
+1. [=Assert=]: |lock|'s [=file lock/type=] is not "`open`".
+1. [=Assert=]: |lockGlobals|'s [=list/contains=] |global|.
+1. [=list/Remove=] the first [=list/item=] in |lockGlobals| equal to |global|.
+1. If |lockGlobals| [=list/is empty=]:
+ 1. Let |pendingLock| be the |file|'s [=file entry/pending lock=].
+ 1. Let |pendingLockGlobals| be the |pendingLock|'s [=file lock/globals=].
+ 1. If |pendingLock|'s [=file lock/type=] is "`open`":
+ 1. [=Assert=]: |pendingLockGlobals| [=list/is empty=].
+ 1. Set |lock|'s [=file lock/type=] to "`open`".
+ 1. Return.
+ 1. [=Assert=]: |pendingLockGlobals|'s [=list/size=] is greater than 0.
+ 1. Set |file|'s [=file entry/lock=] to |pendingLock|.
+ 1. Set |pendingLock|'s [=file lock/type=] to "`open`".
+ 1. [=list/Empty=] |pendingLock|'s [=file lock/globals=].
+ 1. [=set/For each=] |resultSteps| of |file|'s [=file entry/pending steps=]:
+ 1. Run |resultSteps|.
+ 1. [=list/Empty=] |file|'s [=file entry/pending steps=].
Note: These steps have to be run on the [=file system queue=].
@@ -538,7 +585,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 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,20 +622,20 @@ 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=]
- with "`shared`" on |entry|.
-
- 1. [=Queue a storage task=] with |global| to run these steps:
- 1. If |lockResult| is "`failure`", [=/reject=] |result| with a
- "{{NoModificationAllowedError}}" {{DOMException}} and abort these steps.
-
- 1. Let |stream| be the result of
creating a new `FileSystemWritableFileStream`
- for |entry| in |realm|.
- 1. If |options|["{{FileSystemCreateWritableOptions/keepExistingData}}"]
- is true:
- 1. Set |stream|'s [=[[buffer]]=] to a copy of |entry|'s
- [=file entry/binary data=].
- 1. [=/Resolve=] |result| with |stream|.
+ 1. Let |lockResult| be the empty string.
+ 1. [=file entry/Take a lock=] on |entry| with lock type "`shared`", global |global|,
+ lock result |lockResult|, and the following result steps:
+ 1. [=Queue a storage task=] with |global| to run these steps:
+ 1. If |lockResult| is "`failure`", [=/reject=] |result| with a
+ "{{NoModificationAllowedError}}" {{DOMException}} and abort these steps.
+
+ 1. Let |stream| be the result of
creating a new `FileSystemWritableFileStream`
+ for |entry| in |realm| and global |global|.
+ 1. If |options|["{{FileSystemCreateWritableOptions/keepExistingData}}"]
+ is true:
+ 1. Set |stream|'s [=[[buffer]]=] to a copy of |entry|'s
+ [=file entry/binary data=].
+ 1. [=/Resolve=] |result| with |stream|.
1. Return |result|.
@@ -603,7 +650,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 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,16 +692,16 @@ 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=]
- with "`exclusive`" on |entry|.
-
- 1. [=Queue a storage task=] with |global| to run these steps:
- 1. If |lockResult| is "`failure`", [=/reject=] |result| with a
- "{{NoModificationAllowedError}}" {{DOMException}} and abort these steps.
+ 1. Let |lockResult| be the empty string.
+ 1. [=file entry/Take a lock=] on |entry| with lock type "`exclusive`", global |global|,
+ lock result |lockResult|, and the following result steps:
+ 1. [=Queue a storage task=] with |global| to run these steps:
+ 1. If |lockResult| is "`failure`", [=/reject=] |result| with a
+ "{{NoModificationAllowedError}}" {{DOMException}} and abort these steps.
- 1. Let |handle| be the result of
creating a new `FileSystemSyncAccessHandle`
- for |entry| in |realm|.
- 1. [=/Resolve=] |result| with |handle|.
+ 1. Let |handle| be the result of
creating a new `FileSystemSyncAccessHandle`
+ for |entry| in |realm|.
+ 1. [=/Resolve=] |result| with |handle|.
1. Return |result|.
@@ -1151,7 +1198,7 @@ Similarly, when piping a {{ReadableStream}} into a {{FileSystemWritableFileStrea