diff --git a/index.bs b/index.bs index 43da40f..0fc72f2 100644 --- a/index.bs +++ b/index.bs @@ -127,7 +127,7 @@ 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`") +a lock (a [=string=] or null) and a shared lock count (a number representing the number of shared locks that are taken at a given point in time). A user agent has an associated file system queue which is the @@ -135,23 +135,19 @@ result of [=starting a new parallel queue=]. This queue is to be used for all file system operations.
-To take a lock with a |value| of -"`exclusive`" or "`shared`" on a given [=file entry=] |file|: +To take a lock with a |lockType| (a [=string=]) +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=]. -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. If |lock| is null: + 1. Set |lock| to |lockType|. + 1. Set |count| to 1. + 1. Return "`success`". +1. If |lock| is not "`exclusive`": + 1. If |lock| equals |lockType|: + 1. Increase |count| by 1. + 1. Return "`success`". 1. Return "`failure`". Note: These steps have to be run on the [=file system queue=]. @@ -164,10 +160,9 @@ To release a [=file entry/lock=] on a given 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. [=Assert=]: |count| greater than 0. +1. Decrease |count| by 1. +1. If |count| is 0, set |lock| to null. Note: These steps have to be run on the [=file system queue=]. @@ -420,8 +415,24 @@ The isSameEntry(|other|) method steps are ## The {{FileSystemFileHandle}} interface ## {#api-filesystemfilehandle} +enum FileSystemWritableFileStreamMode { + "exclusive", + "siloed", +}; + dictionary FileSystemCreateWritableOptions { boolean keepExistingData = false; + FileSystemWritableFileStreamMode mode = "siloed"; +}; + +enum FileSystemSyncAccessHandleMode { + "readwrite", + "read-only", + "readwrite-unsafe", +}; + +dictionary FileSystemCreateSyncAccessHandleOptions { + FileSystemSyncAccessHandleMode mode = "readwrite"; }; [Exposed=(Window,Worker), SecureContext, Serializable] @@ -429,7 +440,7 @@ interface FileSystemFileHandle : FileSystemHandle { Promise<File> getFile(); Promise<FileSystemWritableFileStream> createWritable(optional FileSystemCreateWritableOptions options = {}); [Exposed=DedicatedWorker] - Promise<FileSystemSyncAccessHandle> createSyncAccessHandle(); + Promise<FileSystemSyncAccessHandle> createSyncAccessHandle(optional FileSystemCreateSyncAccessHandleOptions options = {}); }; @@ -575,8 +586,14 @@ The createWritable(|options|) method |result| with a "{{NotFoundError}}" {{DOMException}} and abort these steps. 1. [=Assert=]: |entry| is a [=file entry=]. + 1. Let |lockType| be a [=string=]. + 1. Let |mode| be |options|["{{FileSystemCreateWritableOptions/mode}}"]. + 1. If |mode| is "`exclusive`": + 1. Set |lockType| to "`exclusive`". + 1. Otherwise, if |mode| is "`siloed`": + 1. Set |lockType| to "`writableSiloed`". 1. Let |lockResult| be the result of [=file entry/take a lock|taking a lock=] - with "`shared`" on |entry|. + with |lockType| on |entry|. 1. [=Queue a storage task=] with |global| to run these steps: 1. If |lockResult| is "`failure`", [=/reject=] |result| with a @@ -617,7 +634,7 @@ The createWritable(|options|) method
-The createSyncAccessHandle() method steps are: +The createSyncAccessHandle(|options|) method steps are: 1. Let |result| be [=a new promise=]. 1. Let |locator| be [=this=]'s [=FileSystemHandle/locator=]. @@ -645,15 +662,27 @@ The createSyncAccessHandle() method s |result| with a "{{NotFoundError}}" {{DOMException}} and abort these steps. 1. [=Assert=]: |entry| is a [=file entry=]. + 1. Let |lockType| be a [=string=]. + 1. Let |writePermission| be a [=string=]. + 1. Let |mode| be |options|["{{FileSystemCreateSyncAccessHandleOptions/mode}}"]. + 1. If |mode| is "`readwrite`": + 1. Set |lockType| to "`exclusive`". + 1. Set |writePermission| to "`writable`". + 1. Otherwise, if |mode| is "`read-only`": + 1. Set |lockType| to "`syncAccessHandleReadOnly`". + 1. Set |writePermission| to "`notWritable`". + 1. Otherwise, if |mode| is "`readwrite-unsafe`": + 1. Set |lockType| to "`syncAccessHandleReadWriteUnsafe`". + 1. Set |writePermission| to "`writable`". 1. Let |lockResult| be the result of [=file entry/take a lock|taking a lock=] - with "`exclusive`" on |entry|. + with |lockType| 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 |handle| be the result of creating a new `FileSystemSyncAccessHandle` - for |entry| in |realm|. + with |entry| and |writePermission| in |realm|. 1. [=/Resolve=] |result| with |handle|. 1. Return |result|. @@ -1440,6 +1469,9 @@ A {{FileSystemSyncAccessHandle}} has an associated \[[state]], a string that may exclusively be "`open`" or "`closed`". +A {{FileSystemSyncAccessHandle}} has an associated \[[writePermission]], +a string that may exclusively be "`writable`" or "`notWritable`". + A {{FileSystemSyncAccessHandle}} is an object that is capable of reading from/writing to, as well as obtaining and changing the size of, a single file. @@ -1451,11 +1483,12 @@ A {{FileSystemSyncAccessHandle}} has a fil
To create a new `FileSystemSyncAccessHandle` -given a [=file entry=] |file| in a [=/Realm=] |realm|: +given a [=file entry=] |file| and a |writePermission| of "`writable`" or "`notWritable`" in a [=/Realm=] |realm|: 1. Let |handle| be a [=new=] {{FileSystemSyncAccessHandle}} in |realm|. 1. Set |handle|'s [=FileSystemSyncAccessHandle/[[file]]=] to |file|. 1. Set |handle|'s [=FileSystemSyncAccessHandle/[[state]]=] to "`open`". +1. Set |handle|'s [=FileSystemSyncAccessHandle/[[writePermission]]=] to |writePermission|. 1. Return |handle|.
@@ -1518,6 +1551,8 @@ The write(|buffer|, {{FileSystemReadW 1. If [=this=]'s [=[[state]]=] is "`closed`", [=throw=] an "{{InvalidStateError}}" {{DOMException}}. +1. If [=this=]'s [=[[writePermission]]=]' is "`notWritable`", + [=throw=] a "{{NoModificationAllowedError}}" {{DOMException}}. 1. Let |writePosition| be |options|["{{FileSystemReadWriteOptions/at}}"] if |options|["{{FileSystemReadWriteOptions/at}}"] [=map/exists=]; otherwise [=this=]'s [=FileSystemSyncAccessHandle/file position cursor=]. @@ -1578,6 +1613,8 @@ The truncate(|newSize|) method 1. If [=this=]'s [=[[state]]=] is "`closed`", [=throw=] an "{{InvalidStateError}}" {{DOMException}}. +1. If [=this=]'s [=[[writePermission]]=]' is "`notWritable`", + [=throw=] a "{{NoModificationAllowedError}}" {{DOMException}}. 1. Let |fileContents| be a copy of [=this=]'s [=FileSystemSyncAccessHandle/[[file]]=]'s [=file entry/binary data=]. 1. Let |oldSize| be the [=byte sequence/length=] of [=this=]'s @@ -1634,6 +1671,8 @@ The flush() method steps are: 1. If [=this=]'s [=[[state]]=] is "`closed`", [=throw=] an "{{InvalidStateError}}" {{DOMException}}. +1. If [=this=]'s [=[[writePermission]]=]' is "`notWritable`", + [=throw=] a "{{NoModificationAllowedError}}" {{DOMException}}. 1. Attempt to transfer all cached modifications of the file's content to the file system's underlying storage device.