@@ -124,34 +124,35 @@ Issue: We should consider having further normative restrictions on file names th
124
124
never be allowed using this API, rather than leaving it entirely up to underlying file
125
125
systems.
126
126
127
+ A <dfn>lock type</dfn> is a [=string=] that may exclusively be "`open`",
128
+ "`exclusive`", "`writable-siloed`", "`sync-access-handle-read-only`",
129
+ "`sync-access-handle-read-write-unsafe`".
130
+
127
131
A <dfn export id=file>file entry</dfn> additionally consists of
128
132
<dfn for="file entry" export>binary data</dfn> (a [=byte sequence=] ), a
129
133
<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`")
131
- 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).
134
+ a <dfn for="file entry">lock</dfn> (a [=lock type=] ),
135
+ and a <dfn for="file entry">lock count</dfn> (a number representing the number of locks that are taken at a given point in time).
132
136
133
137
A user agent has an associated <dfn>file system queue</dfn> which is the
134
138
result of [=starting a new parallel queue=] . This queue is to be used for all
135
139
file system operations.
136
140
137
141
<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|:
142
+ To <dfn for="file entry" id=file-entry-lock-take>take a lock</dfn> with a |lockType| (a [=lock type=] )
143
+ on a given [=file entry=] |file|:
140
144
145
+ 1. [=Assert=] : |lockType| is not "`open`".
141
146
1. Let |lock| be the |file|'s [=file entry/lock=] .
142
- 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`".
147
+ 1. Let |count| be the |file|'s [=file entry/lock count=] .
148
+ 1. If |lock| is "`open`":
149
+ 1. Set |lock| to |lockType|.
150
+ 1. Set |count| to 1.
151
+ 1. Return "`success`".
152
+ 1. If |lock| is not "`exclusive`":
153
+ 1. If |lock| equals |lockType|:
154
+ 1. Increase |count| by 1.
155
+ 1. Return "`success`".
155
156
1. Return "`failure`".
156
157
157
158
Note: These steps have to be run on the [=file system queue=] .
@@ -163,18 +164,16 @@ To <dfn for="file entry/lock">release</dfn> a [=file entry/lock=] on a given
163
164
[=file entry=] |file|:
164
165
165
166
1. Let |lock| be the |file|'s associated [=file entry/lock=] .
166
- 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`".
167
+ 1. Let |count| be the |file|'s [=file entry/lock count=] .
168
+ 1. [=Assert=] : |count| is greater than 0.
169
+ 1. Decrease |count| by 1.
170
+ 1. If |count| is 0, set |lock| to "`open`".
171
171
172
172
Note: These steps have to be run on the [=file system queue=] .
173
173
174
174
</div>
175
175
176
- Note: Locks help prevent concurrent modifications to a file. A {{FileSystemWritableFileStream}}
177
- requires a shared lock, while a {{FileSystemSyncAccessHandle}} requires an exclusive one.
176
+ Note: Locks help prevent concurrent modifications to a file that are incompatible.
178
177
179
178
A <dfn export id=directory>directory entry</dfn> additionally consists of a [=/set=] of
180
179
<dfn for="directory entry">children</dfn> , which are themselves [=/file system entries=] .
@@ -420,16 +419,32 @@ The <dfn method for=FileSystemHandle>isSameEntry(|other|)</dfn> method steps are
420
419
## The {{FileSystemFileHandle}} interface ## {#api-filesystemfilehandle}
421
420
422
421
<xmp class=idl>
422
+ enum FileSystemWritableFileStreamMode {
423
+ "exclusive",
424
+ "siloed",
425
+ };
426
+
423
427
dictionary FileSystemCreateWritableOptions {
424
428
boolean keepExistingData = false;
429
+ FileSystemWritableFileStreamMode mode = "siloed";
430
+ };
431
+
432
+ enum FileSystemSyncAccessHandleMode {
433
+ "readwrite",
434
+ "read-only",
435
+ "readwrite-unsafe",
436
+ };
437
+
438
+ dictionary FileSystemCreateSyncAccessHandleOptions {
439
+ FileSystemSyncAccessHandleMode mode = "readwrite";
425
440
};
426
441
427
442
[Exposed=(Window,Worker), SecureContext, Serializable]
428
443
interface FileSystemFileHandle : FileSystemHandle {
429
444
Promise<File> getFile();
430
445
Promise<FileSystemWritableFileStream> createWritable(optional FileSystemCreateWritableOptions options = {});
431
446
[Exposed=DedicatedWorker]
432
- Promise<FileSystemSyncAccessHandle> createSyncAccessHandle();
447
+ Promise<FileSystemSyncAccessHandle> createSyncAccessHandle(optional FileSystemCreateSyncAccessHandleOptions options = {} );
433
448
};
434
449
</xmp>
435
450
@@ -538,10 +553,12 @@ The <dfn method for=FileSystemFileHandle>getFile()</dfn> method steps are:
538
553
the temporary file starts out empty,
539
554
otherwise the existing file is first copied to this temporary file.
540
555
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.
556
+ Creating a {{FileSystemWritableFileStream}} [=file entry/take a lock|takes a lock=] on the
557
+ [=file entry=] [=locate an entry|locatable=] with |fileHandle|'s [=FileSystemHandle/locator=]
558
+ and a |lockType| determined by {{FileSystemCreateWritableOptions/mode}} . Until the stream is
559
+ closed, both {{FileSystemCreateWritableOptions/mode|modes}} prevent any file operation or the
560
+ creation of a file primitive on the [=file entry=] , but "`siloed`" will allow the creation of other
561
+ {{FileSystemWritableFileStream}} in "`siloed`" {{FileSystemCreateWritableOptions/mode}} .
545
562
</div>
546
563
547
564
<p class=XXX> See <a href=https://github.com/WICG/file-system-access/issues/67>WICG/file-system-access issue #67</a>
@@ -575,8 +592,15 @@ The <dfn method for=FileSystemFileHandle>createWritable(|options|)</dfn> method
575
592
|result| with a "{{NotFoundError}} " {{DOMException}} and abort these steps.
576
593
1. [=Assert=] : |entry| is a [=file entry=] .
577
594
595
+ 1. Let |lockType| be the empty string.
596
+ 1. Let |mode| be |options|["{{FileSystemCreateWritableOptions/mode}}"] .
597
+ 1. If |mode| is "`exclusive`":
598
+ 1. Set |lockType| to "`exclusive`".
599
+ 1. Otherwise:
600
+ 1. [=Assert=] : |mode| is "`siloed`".
601
+ 1. Set |lockType| to "`writable-siloed`".
578
602
1. Let |lockResult| be the result of [=file entry/take a lock|taking a lock=]
579
- with "`shared`" on |entry|.
603
+ with |lockType| on |entry|.
580
604
581
605
1. [=Queue a storage task=] with |global| to run these steps:
582
606
1. If |lockResult| is "`failure`", [=/reject=] |result| with a
@@ -603,11 +627,12 @@ The <dfn method for=FileSystemFileHandle>createWritable(|options|)</dfn> method
603
627
[=file entry=] [=locate an entry|locatable=] by |fileHandle|'s [=FileSystemHandle/locator=] .
604
628
To ensure the changes are reflected in this file, the handle can be flushed.
605
629
606
- Creating a {{FileSystemSyncAccessHandle}} [=file entry/take a lock|takes an exclusive lock=] on the
607
- [=file entry=] [=locate an entry|locatable=] with |fileHandle|'s [=FileSystemHandle/locator=] .
608
- This prevents the creation of further {{FileSystemSyncAccessHandle|FileSystemSyncAccessHandles}}
609
- or {{FileSystemWritableFileStream|FileSystemWritableFileStreams}}
610
- for the entry, until the access handle is closed.
630
+ Creating a {{FileSystemSyncAccessHandle}} [=file entry/take a lock|takes a lock=] on the
631
+ [=file entry=] [=locate an entry|locatable=] with |fileHandle|'s [=FileSystemHandle/locator=]
632
+ and a |lockType| determined by {{FileSystemCreateSyncAccessHandleOptions/mode}} . Until the access handle is
633
+ closed, all {{FileSystemCreateSyncAccessHandleOptions/mode|modes}} prevent any file operation or the
634
+ creation of a file primitive on the [=file entry=] , but "`read-only`" and "`readwrite-unsafe`" will allow the creation of other
635
+ {{FileSystemSyncAccessHandle}} in their respective {{FileSystemCreateSyncAccessHandleOptions/mode|modes}} .
611
636
612
637
The returned {{FileSystemSyncAccessHandle}} offers synchronous methods. This allows for higher performance
613
638
on contexts where asynchronous operations come with high overhead, e.g., WebAssembly.
@@ -617,7 +642,7 @@ The <dfn method for=FileSystemFileHandle>createWritable(|options|)</dfn> method
617
642
</div>
618
643
619
644
<div algorithm>
620
- The <dfn method for=FileSystemFileHandle>createSyncAccessHandle()</dfn> method steps are:
645
+ The <dfn method for=FileSystemFileHandle>createSyncAccessHandle(|options| )</dfn> method steps are:
621
646
622
647
1. Let |result| be [=a new promise=] .
623
648
1. Let |locator| be [=this=] 's [=FileSystemHandle/locator=] .
@@ -645,15 +670,28 @@ The <dfn method for=FileSystemFileHandle>createSyncAccessHandle()</dfn> method s
645
670
|result| with a "{{NotFoundError}} " {{DOMException}} and abort these steps.
646
671
1. [=Assert=] : |entry| is a [=file entry=] .
647
672
673
+ 1. Let |lockType| be the empty string.
674
+ 1. Let |writeAccess| be the empty string.
675
+ 1. Let |mode| be |options|["{{FileSystemCreateSyncAccessHandleOptions/mode}}"] .
676
+ 1. If |mode| is "`readwrite`":
677
+ 1. Set |lockType| to "`exclusive`".
678
+ 1. Set |writeAccess| to "`writable`".
679
+ 1. Otherwise, if |mode| is "`read-only`":
680
+ 1. Set |lockType| to "`sync-access-handle-read-only`".
681
+ 1. Set |writeAccess| to "`not-writable`".
682
+ 1. Otherwise:
683
+ 1. [=Assert=] : |mode| is "`readwrite-unsafe`".
684
+ 1. Set |lockType| to "`sync-access-handle-read-write-unsafe`".
685
+ 1. Set |writeAccess| to "`writable`".
648
686
1. Let |lockResult| be the result of [=file entry/take a lock|taking a lock=]
649
- with "`exclusive`" on |entry|.
687
+ with |lockType| on |entry|.
650
688
651
689
1. [=Queue a storage task=] with |global| to run these steps:
652
690
1. If |lockResult| is "`failure`", [=/reject=] |result| with a
653
691
"{{NoModificationAllowedError}} " {{DOMException}} and abort these steps.
654
692
655
693
1. Let |handle| be the result of <a>creating a new `FileSystemSyncAccessHandle`</a>
656
- for |entry| in |realm|.
694
+ with |entry| and |writeAccess | in |realm|.
657
695
1. [=/Resolve=] |result| with |handle|.
658
696
659
697
1. Return |result|.
@@ -1440,6 +1478,9 @@ A {{FileSystemSyncAccessHandle}} has an associated <dfn for=FileSystemSyncAccess
1440
1478
A {{FileSystemSyncAccessHandle}} has an associated <dfn for=FileSystemSyncAccessHandle>\[[state]]</dfn> ,
1441
1479
a string that may exclusively be "`open`" or "`closed`".
1442
1480
1481
+ A {{FileSystemSyncAccessHandle}} has an associated <dfn for=FileSystemSyncAccessHandle>\[[writeAccess]]</dfn> ,
1482
+ a [=string=] that may exclusively be "`writable`" or "`not-writable`".
1483
+
1443
1484
A {{FileSystemSyncAccessHandle}} is an object that is capable of reading from/writing to,
1444
1485
as well as obtaining and changing the size of, a single file.
1445
1486
@@ -1451,11 +1492,13 @@ A {{FileSystemSyncAccessHandle}} has a <dfn for="FileSystemSyncAccessHandle">fil
1451
1492
<div algorithm>
1452
1493
To
1453
1494
<dfn local-lt="creating a new FileSystemSyncAccessHandle">create a new `FileSystemSyncAccessHandle`</dfn>
1454
- given a [=file entry=] |file| in a [=/Realm=] |realm|:
1495
+ given a [=file entry=] |file| and a [=string=] |writeAccess| in a [=/Realm=] |realm|:
1455
1496
1497
+ 1. [=Assert=] : |writeAccess| is "`writable`" or "`not-writable`".
1456
1498
1. Let |handle| be a [=new=] {{FileSystemSyncAccessHandle}} in |realm|.
1457
1499
1. Set |handle|'s [=FileSystemSyncAccessHandle/[[file]]=] to |file|.
1458
1500
1. Set |handle|'s [=FileSystemSyncAccessHandle/[[state]]=] to "`open`".
1501
+ 1. Set |handle|'s [=FileSystemSyncAccessHandle/[[writeAccess]]=] to |writeAccess|.
1459
1502
1. Return |handle|.
1460
1503
1461
1504
</div>
@@ -1518,6 +1561,8 @@ The <dfn method for=FileSystemSyncAccessHandle>write(|buffer|, {{FileSystemReadW
1518
1561
1519
1562
1. If [=this=] 's [=[[state]]=] is "`closed`",
1520
1563
[=throw=] an "{{InvalidStateError}} " {{DOMException}} .
1564
+ 1. If [=this=] 's [=[[writeAccess]]=]' is "`not-writable`",
1565
+ [=throw=] a "{{NoModificationAllowedError}} " {{DOMException}} .
1521
1566
1. Let |writePosition| be |options|["{{FileSystemReadWriteOptions/at}}"] if
1522
1567
|options|["{{FileSystemReadWriteOptions/at}}"] [=map/exists=] ; otherwise
1523
1568
[=this=] 's [=FileSystemSyncAccessHandle/file position cursor=] .
@@ -1578,6 +1623,8 @@ The <dfn method for=FileSystemSyncAccessHandle>truncate(|newSize|)</dfn> method
1578
1623
1579
1624
1. If [=this=] 's [=[[state]]=] is "`closed`",
1580
1625
[=throw=] an "{{InvalidStateError}} " {{DOMException}} .
1626
+ 1. If [=this=] 's [=[[writeAccess]]=]' is "`not-writable`",
1627
+ [=throw=] a "{{NoModificationAllowedError}} " {{DOMException}} .
1581
1628
1. Let |fileContents| be a copy of [=this=] 's
1582
1629
[=FileSystemSyncAccessHandle/[[file]]=] 's [=file entry/binary data=] .
1583
1630
1. Let |oldSize| be the [=byte sequence/length=] of [=this=] 's
@@ -1634,6 +1681,8 @@ The <dfn method for=FileSystemSyncAccessHandle>flush()</dfn> method steps are:
1634
1681
1635
1682
1. If [=this=] 's [=[[state]]=] is "`closed`",
1636
1683
[=throw=] an "{{InvalidStateError}} " {{DOMException}} .
1684
+ 1. If [=this=] 's [=[[writeAccess]]=]' is "`not-writable`",
1685
+ [=throw=] a "{{NoModificationAllowedError}} " {{DOMException}} .
1637
1686
1. Attempt to transfer all cached modifications of the file's content to the
1638
1687
file system's underlying storage device.
1639
1688
0 commit comments