Skip to content

Commit 0eb043a

Browse files
author
Nathan Memmott
committed
Add new SAH and WFS locking modes
Adds new locking modes for sync access handles and writable file streams. Updates "file entry/take a lock" and "file entry/lock/release" to support these new modes.
1 parent b03688d commit 0eb043a

File tree

1 file changed

+84
-29
lines changed

1 file changed

+84
-29
lines changed

index.bs

Lines changed: 84 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -127,31 +127,29 @@ systems.
127127
A <dfn export id=file>file entry</dfn> additionally consists of
128128
<dfn for="file entry" export>binary data</dfn> (a [=byte sequence=]), a
129129
<dfn for="file entry">modification timestamp</dfn> (a number representing the number of milliseconds since the <a spec=FileAPI>Unix Epoch</a>),
130-
a <dfn for="file entry">lock</dfn> (a string that may exclusively be "`open`", "`taken-exclusive`" or "`taken-shared`")
130+
a <dfn for="file entry">lock</dfn> (a [=string=] that may exclusively be "`open`", "`exclusive`", "`writableSiloed`",
131+
"`syncAccessHandleReadOnly`", "`syncAccessHandleReadWriteUnsafe`")
131132
and a <dfn for="file entry">shared lock count</dfn> (a number representing the number of shared locks that are taken at a given point in time).
132133

133134
A user agent has an associated <dfn>file system queue</dfn> which is the
134135
result of [=starting a new parallel queue=]. This queue is to be used for all
135136
file system operations.
136137

137138
<div algorithm>
138-
To <dfn for="file entry" id=file-entry-lock-take>take a lock</dfn> with a |value| of
139-
"`exclusive`" or "`shared`" on a given [=file entry=] |file|:
139+
To <dfn for="file entry" id=file-entry-lock-take>take a lock</dfn> with a |lockType| (a [=string=])
140+
on a given [=file entry=] |file|:
140141

142+
1. [=Assert=]: |lockType| is "`exclusive`", "`writableSiloed`", "`syncAccessHandleReadOnly`", or "`syncAccessHandleReadWriteUnsafe`".
141143
1. Let |lock| be the |file|'s [=file entry/lock=].
142144
1. Let |count| be the |file|'s [=file entry/shared lock count=].
143-
1. If |value| is "`exclusive`":
144-
1. If |lock| is "`open`":
145-
1. Set lock to "`taken-exclusive`".
146-
1. Return "`success`".
147-
1. If |value| is "`shared`":
148-
1. If |lock| is "`open`":
149-
1. Set |lock| to "`taken-shared`".
150-
1. Set |count| to 1.
151-
1. Return "`success`".
152-
1. Otherwise, if |lock| is "`taken-shared`":
153-
1. Increase |count| by 1.
154-
1. Return "`success`".
145+
1. If |lock| is null:
146+
1. Set |lock| to |lockType|.
147+
1. Set |count| to 1.
148+
1. Return "`success`".
149+
1. If |lock| is not "`exclusive`":
150+
1. If |lock| equals |lockType|:
151+
1. Increase |count| by 1.
152+
1. Return "`success`".
155153
1. Return "`failure`".
156154

157155
Note: These steps have to be run on the [=file system queue=].
@@ -164,10 +162,9 @@ To <dfn for="file entry/lock">release</dfn> a [=file entry/lock=] on a given
164162

165163
1. Let |lock| be the |file|'s associated [=file entry/lock=].
166164
1. Let |count| be the |file|'s [=file entry/shared lock count=].
167-
1. If |lock| is "`taken-shared`":
168-
1. Decrease |count| by 1.
169-
1. If |count| is 0, set |lock| to "`open`".
170-
1. Otherwise, set |lock| to "`open`".
165+
1. [=Assert=]: |count| is greater than 0.
166+
1. Decrease |count| by 1.
167+
1. If |count| is 0, set |lock| to null.
171168

172169
Note: These steps have to be run on the [=file system queue=].
173170

@@ -420,16 +417,32 @@ The <dfn method for=FileSystemHandle>isSameEntry(|other|)</dfn> method steps are
420417
## The {{FileSystemFileHandle}} interface ## {#api-filesystemfilehandle}
421418

422419
<xmp class=idl>
420+
enum FileSystemWritableFileStreamMode {
421+
"exclusive",
422+
"siloed",
423+
};
424+
423425
dictionary FileSystemCreateWritableOptions {
424426
boolean keepExistingData = false;
427+
FileSystemWritableFileStreamMode mode = "siloed";
428+
};
429+
430+
enum FileSystemSyncAccessHandleMode {
431+
"readwrite",
432+
"read-only",
433+
"readwrite-unsafe",
434+
};
435+
436+
dictionary FileSystemCreateSyncAccessHandleOptions {
437+
FileSystemSyncAccessHandleMode mode = "readwrite";
425438
};
426439

427440
[Exposed=(Window,Worker), SecureContext, Serializable]
428441
interface FileSystemFileHandle : FileSystemHandle {
429442
Promise<File> getFile();
430443
Promise<FileSystemWritableFileStream> createWritable(optional FileSystemCreateWritableOptions options = {});
431444
[Exposed=DedicatedWorker]
432-
Promise<FileSystemSyncAccessHandle> createSyncAccessHandle();
445+
Promise<FileSystemSyncAccessHandle> createSyncAccessHandle(optional FileSystemCreateSyncAccessHandleOptions options = {});
433446
};
434447
</xmp>
435448

@@ -538,10 +551,13 @@ The <dfn method for=FileSystemFileHandle>getFile()</dfn> method steps are:
538551
the temporary file starts out empty,
539552
otherwise the existing file is first copied to this temporary file.
540553

541-
Creating a {{FileSystemWritableFileStream}} [=file entry/take a lock|takes a shared lock=] on the
542-
[=file entry=] [=locate an entry|locatable=] with |fileHandle|'s [=FileSystemHandle/locator=].
543-
This prevents the creation of {{FileSystemSyncAccessHandle|FileSystemSyncAccessHandles}}
544-
for the entry, until the stream is closed.
554+
Creating a {{FileSystemWritableFileStream}} [=file entry/take a lock|takes a lock=] on the
555+
[=file entry=] [=locate an entry|locatable=] with |fileHandle|'s [=FileSystemHandle/locator=]
556+
and a |lockType| determined by {{FileSystemCreateWritableOptions/mode}}. Until the stream is
557+
closed, both {{FileSystemCreateWritableOptions/mode|modes}} prevent the creation on the entry
558+
of a {{FileSystemWritableFileStream}} in a different {{FileSystemCreateWritableOptions/mode}}
559+
or a {{FileSystemSyncAccessHandle}}, but "`exclusive`" will also prevent the creation of
560+
{{FileSystemWritableFileStream}} in "`exclusive`" {{FileSystemCreateWritableOptions/mode}}.
545561
</div>
546562

547563
<p class=XXX>See <a href=https://github.com/WICG/file-system-access/issues/67>WICG/file-system-access issue #67</a>
@@ -575,8 +591,15 @@ The <dfn method for=FileSystemFileHandle>createWritable(|options|)</dfn> method
575591
|result| with a "{{NotFoundError}}" {{DOMException}} and abort these steps.
576592
1. [=Assert=]: |entry| is a [=file entry=].
577593

594+
1. Let |lockType| be the empty string.
595+
1. Let |mode| be |options|["{{FileSystemCreateWritableOptions/mode}}"].
596+
1. If |mode| is "`exclusive`":
597+
1. Set |lockType| to "`exclusive`".
598+
1. Otherwise:
599+
1. [=Assert=]: |mode| is "`siloed`".
600+
1. Set |lockType| to "`writableSiloed`".
578601
1. Let |lockResult| be the result of [=file entry/take a lock|taking a lock=]
579-
with "`shared`" on |entry|.
602+
with |lockType| on |entry|.
580603

581604
1. [=Queue a storage task=] with |global| to run these steps:
582605
1. If |lockResult| is "`failure`", [=/reject=] |result| with a
@@ -609,6 +632,14 @@ The <dfn method for=FileSystemFileHandle>createWritable(|options|)</dfn> method
609632
or {{FileSystemWritableFileStream|FileSystemWritableFileStreams}}
610633
for the entry, until the access handle is closed.
611634

635+
Creating a {{FileSystemSyncAccessHandle}} [=file entry/take a lock|takes a lock=] on the
636+
[=file entry=] [=locate an entry|locatable=] with |fileHandle|'s [=FileSystemHandle/locator=]
637+
and a |lockType| determined by {{FileSystemCreateSyncAccessHandleOptions/mode}}. Until the access handle is
638+
closed, all {{FileSystemCreateSyncAccessHandleOptions/mode|modes}} prevent the creation on the entry
639+
of a {{FileSystemSyncAccessHandle}} in a different {{FileSystemCreateSyncAccessHandleOptions/mode}}
640+
or a {{FileSystemWritableFileStream}}, but "`read-write`" will also prevent the creation of
641+
{{FileSystemSyncAccessHandle}} in "`read-write`" {{FileSystemCreateSyncAccessHandleOptions/mode}}.
642+
612643
The returned {{FileSystemSyncAccessHandle}} offers synchronous methods. This allows for higher performance
613644
on contexts where asynchronous operations come with high overhead, e.g., WebAssembly.
614645

@@ -617,7 +648,7 @@ The <dfn method for=FileSystemFileHandle>createWritable(|options|)</dfn> method
617648
</div>
618649

619650
<div algorithm>
620-
The <dfn method for=FileSystemFileHandle>createSyncAccessHandle()</dfn> method steps are:
651+
The <dfn method for=FileSystemFileHandle>createSyncAccessHandle(|options|)</dfn> method steps are:
621652

622653
1. Let |result| be [=a new promise=].
623654
1. Let |locator| be [=this=]'s [=FileSystemHandle/locator=].
@@ -645,15 +676,28 @@ The <dfn method for=FileSystemFileHandle>createSyncAccessHandle()</dfn> method s
645676
|result| with a "{{NotFoundError}}" {{DOMException}} and abort these steps.
646677
1. [=Assert=]: |entry| is a [=file entry=].
647678

679+
1. Let |lockType| be the empty string.
680+
1. Let |writeAccess| be the empty string.
681+
1. Let |mode| be |options|["{{FileSystemCreateSyncAccessHandleOptions/mode}}"].
682+
1. If |mode| is "`readwrite`":
683+
1. Set |lockType| to "`exclusive`".
684+
1. Set |writeAccess| to "`writable`".
685+
1. Otherwise, if |mode| is "`read-only`":
686+
1. Set |lockType| to "`syncAccessHandleReadOnly`".
687+
1. Set |writeAccess| to "`not-writable`".
688+
1. Otherwise:
689+
1. [=Assert=]: |mode| is "`readwrite-unsafe`".
690+
1. Set |lockType| to "`syncAccessHandleReadWriteUnsafe`".
691+
1. Set |writeAccess| to "`writable`".
648692
1. Let |lockResult| be the result of [=file entry/take a lock|taking a lock=]
649-
with "`exclusive`" on |entry|.
693+
with |lockType| on |entry|.
650694

651695
1. [=Queue a storage task=] with |global| to run these steps:
652696
1. If |lockResult| is "`failure`", [=/reject=] |result| with a
653697
"{{NoModificationAllowedError}}" {{DOMException}} and abort these steps.
654698

655699
1. Let |handle| be the result of <a>creating a new `FileSystemSyncAccessHandle`</a>
656-
for |entry| in |realm|.
700+
with |entry| and |writeAccess| in |realm|.
657701
1. [=/Resolve=] |result| with |handle|.
658702

659703
1. Return |result|.
@@ -1440,6 +1484,9 @@ A {{FileSystemSyncAccessHandle}} has an associated <dfn for=FileSystemSyncAccess
14401484
A {{FileSystemSyncAccessHandle}} has an associated <dfn for=FileSystemSyncAccessHandle>\[[state]]</dfn>,
14411485
a string that may exclusively be "`open`" or "`closed`".
14421486

1487+
A {{FileSystemSyncAccessHandle}} has an associated <dfn for=FileSystemSyncAccessHandle>\[[writeAccess]]</dfn>,
1488+
a string that may exclusively be "`writable`" or "`not-writable`".
1489+
14431490
A {{FileSystemSyncAccessHandle}} is an object that is capable of reading from/writing to,
14441491
as well as obtaining and changing the size of, a single file.
14451492

@@ -1451,11 +1498,13 @@ A {{FileSystemSyncAccessHandle}} has a <dfn for="FileSystemSyncAccessHandle">fil
14511498
<div algorithm>
14521499
To
14531500
<dfn local-lt="creating a new FileSystemSyncAccessHandle">create a new `FileSystemSyncAccessHandle`</dfn>
1454-
given a [=file entry=] |file| in a [=/Realm=] |realm|:
1501+
given a [=file entry=] |file| and a [=string=] |writeAccess| in a [=/Realm=] |realm|:
14551502

1503+
1. [=Assert=]: |writeAccess| is "`writable`" or "`notWritable`".
14561504
1. Let |handle| be a [=new=] {{FileSystemSyncAccessHandle}} in |realm|.
14571505
1. Set |handle|'s [=FileSystemSyncAccessHandle/[[file]]=] to |file|.
14581506
1. Set |handle|'s [=FileSystemSyncAccessHandle/[[state]]=] to "`open`".
1507+
1. Set |handle|'s [=FileSystemSyncAccessHandle/[[writeAccess]]=] to |writeAccess|.
14591508
1. Return |handle|.
14601509

14611510
</div>
@@ -1518,6 +1567,8 @@ The <dfn method for=FileSystemSyncAccessHandle>write(|buffer|, {{FileSystemReadW
15181567

15191568
1. If [=this=]'s [=[[state]]=] is "`closed`",
15201569
[=throw=] an "{{InvalidStateError}}" {{DOMException}}.
1570+
1. If [=this=]'s [=[[writeAccess]]=]' is "`not-writable`",
1571+
[=throw=] a "{{NoModificationAllowedError}}" {{DOMException}}.
15211572
1. Let |writePosition| be |options|["{{FileSystemReadWriteOptions/at}}"] if
15221573
|options|["{{FileSystemReadWriteOptions/at}}"] [=map/exists=]; otherwise
15231574
[=this=]'s [=FileSystemSyncAccessHandle/file position cursor=].
@@ -1578,6 +1629,8 @@ The <dfn method for=FileSystemSyncAccessHandle>truncate(|newSize|)</dfn> method
15781629

15791630
1. If [=this=]'s [=[[state]]=] is "`closed`",
15801631
[=throw=] an "{{InvalidStateError}}" {{DOMException}}.
1632+
1. If [=this=]'s [=[[writeAccess]]=]' is "`not-writable`",
1633+
[=throw=] a "{{NoModificationAllowedError}}" {{DOMException}}.
15811634
1. Let |fileContents| be a copy of [=this=]'s
15821635
[=FileSystemSyncAccessHandle/[[file]]=]'s [=file entry/binary data=].
15831636
1. Let |oldSize| be the [=byte sequence/length=] of [=this=]'s
@@ -1634,6 +1687,8 @@ The <dfn method for=FileSystemSyncAccessHandle>flush()</dfn> method steps are:
16341687

16351688
1. If [=this=]'s [=[[state]]=] is "`closed`",
16361689
[=throw=] an "{{InvalidStateError}}" {{DOMException}}.
1690+
1. If [=this=]'s [=[[writeAccess]]=]' is "`not-writable`",
1691+
[=throw=] a "{{NoModificationAllowedError}}" {{DOMException}}.
16371692
1. Attempt to transfer all cached modifications of the file's content to the
16381693
file system's underlying storage device.
16391694

0 commit comments

Comments
 (0)