Skip to content

Commit 91fbb6d

Browse files
committed
Fill in read, write, close
1 parent 3c94fea commit 91fbb6d

File tree

1 file changed

+71
-17
lines changed

1 file changed

+71
-17
lines changed

index.bs

Lines changed: 71 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -539,8 +539,6 @@ currently implemented in Chrome. Implementing this is currently blocked on figur
539539
combine the desire to run malware checks with the desire to let websites make fast in-place
540540
modifications to existing large files.
541541

542-
// TODO(fivedots): release lock once the stream is closed.
543-
544542
<div algorithm>
545543
The <dfn method for=FileSystemFileHandle>createWritable(|options|)</dfn> method, when invoked, must run these steps:
546544

@@ -1038,13 +1036,17 @@ in a [=/Realm=] |realm|, perform the following steps:
10381036

10391037
Note: It is expected that this atomically updates the contents of the file on disk
10401038
being written to.
1039+
1. [=file entry/lock/release|Release the lock=] on |stream|.[=FileSystemWritableFileStream/[[file]]=].
10411040
1. [=/Resolve=] |closeResult| with `undefined`.
10421041
1. Return |closeResult|.
1042+
1. Let |abortAlgorithm| be the following step:
1043+
1. [=file entry/lock/release|Release the lock=] on |stream|.[=FileSystemWritableFileStream/[[file]]=].
10431044
1. Let |highWaterMark| be 1.
10441045
1. Let |sizeAlgorithm| be an algorithm that returns `1`.
10451046
1. [=WritableStream/Set up=] |stream| with <a for="WritableStream/set up"><var
10461047
ignore>writeAlgorithm</var></a> set to |writeAlgorithm|, <a for="WritableStream/set up"><var
10471048
ignore>closeAlgorithm</var></a> set to |closeAlgorithm|, <a for="WritableStream/set up"><var
1049+
ignore>abortAlgorithm</var></a> set to |abortAlgorithm|, <a for="WritableStream/set up"><var
10481050
ignore>highWaterMark</var></a> set to |highWaterMark|, and <a for="WritableStream/set up"><var
10491051
ignore>sizeAlgorithm</var></a> set to |sizeAlgorithm|.
10501052
1. Return |stream|.
@@ -1246,7 +1248,7 @@ steps:
12461248
<xmp class=idl>
12471249

12481250
dictionary FilesystemReadWriteOptions {
1249-
[EnforceRange] unsigned long long at;
1251+
[EnforceRange] required unsigned long long at;
12501252
}
12511253

12521254
[Exposed=DedicatedWorker, SecureContext]
@@ -1264,7 +1266,11 @@ interface FileSystemSyncAccessHandle {
12641266

12651267
</xmp>
12661268

1267-
A {{FileSystemSyncAccessHandle}} has an associated <dfn for=FileSystemSyncAccessHandle>\[[file]]</dfn> (a [=file entry=]).
1269+
A {{FileSystemSyncAccessHandle}} has an associated <dfn for=FileSystemSyncAccessHandle>\[[file]]</dfn>
1270+
(a [=file entry=]).
1271+
1272+
A {{FileSystemSyncAccessHandle}} has an associated <dfn for=FileSystemSyncAccessHandle>\[[state]]</dfn>,
1273+
a string that may exclusively be "open" or "closed".
12681274

12691275
<div class="note domintro">
12701276

@@ -1283,37 +1289,81 @@ in a [=/Realm=] |realm|, perform the following steps:
12831289

12841290
1. Let |handle| be a [=new=] {{FileSystemSyncAccessHandle}} in |realm|.
12851291
1. Set |handle|.[=FileSystemSyncAccessHandle/[[file]]=] to |file|.
1292+
1. Set |handle|.[=FileSystemSyncAccessHandle/[[state]]=] to "open".
12861293
1. Return |handle|.
12871294

12881295
</div>
12891296

12901297
### The {{FileSystemSyncAccessHandle/read()}} method ### {#api-filesystemsyncaccesshandle-read}
12911298

12921299
<div class="note domintro">
1293-
: |handle| . {{FileSystemSyncAccessHandle/read()|read}}(|buffer|, {{FilesystemReadWriteOptions/at}}: |position|)
1294-
:: Reads the contents of the file associated with |handle| into |buffer|, with |position| as the offset.
1300+
: |handle| . {{FileSystemSyncAccessHandle/read()|read}}(|buffer|, {{FilesystemReadWriteOptions}}: |options|
1301+
:: Reads the contents of the file associated with |handle| into |buffer|, with |options|.{{FilesystemReadWriteOptions/at}} as the offset.
12951302
</div>
12961303

1304+
// TODO(fivedots): Is there a more formal way to describe the resutl of partial reads from the OS?
12971305
<div algorithm>
1298-
The <dfn method for=FileSystemSyncAccessHandle>read(|buffer|, {{FilesystemReadWriteOptions/at}}: |position|)</dfn> method, when invoked, must run
1306+
The <dfn method for=FileSystemSyncAccessHandle>read(|buffer|, {{FilesystemReadWriteOptions}}: |options|)</dfn> method, when invoked, must run
12991307
these steps:
13001308

1301-
// TODO(fivedots): fill in. Does this algorithm need to check that the access handle has not been closed?
1309+
1. If [=this=].[=[[state]]=] is "closed", throw a {{InvalidStateError}}.
1310+
1. Let |readPosition| be |options|.{{FilesystemReadWriteOptions/at}}.
1311+
1. Let |size| be |buffer|'s [=byte length=].
1312+
1. Let |result| be |size|.
1313+
1. Let |bytes| be a [=byte sequence=] containing the bytes from |readPosition|
1314+
to |readPosition| + (|size| - 1) of [=this=].[=[[file]]=]'s [=file entry/binary data=].
1315+
1. If the operations reading from [=this=].[=[[file]]=]'s [=file entry/binary data=] in the previous steps
1316+
failed:
1317+
1. If there were partial reads and the number of modified bytes in |bytes| is known,
1318+
set |result| to the number of modified bytes.
1319+
1. Else set |result| to 0.
1320+
1. Let |arrayBuffer| be |buffer|'s [=underlying buffer=].
1321+
1. [=write|Write=] |bytes| into |arrayBuffer|.
1322+
1. Return |result|.
13021323

13031324
</div>
13041325

13051326
### The {{FileSystemSyncAccessHandle/write()}} method ### {#api-filesystemsyncaccesshandle-write}
13061327

13071328
<div class="note domintro">
1308-
: |handle| . {{FileSystemSyncAccessHandle/write()|write}}(|buffer|, {{FilesystemReadWriteOptions/at}}: |position|)
1309-
:: Writes the content of |buffer| into the file associated with |handle| with |position| as the offset.
1329+
: |handle| . {{FileSystemSyncAccessHandle/write()|write}}(|buffer|, {{FilesystemReadWriteOptions}}: |options|)
1330+
:: Writes the content of |buffer| into the file associated with |handle| with |options|.{{FilesystemReadWriteOptions/at}} as the offset.
13101331
</div>
13111332

1333+
// TODO(fivedots): Is there a more formal way to describe the resutl of partial writes from the OS?
1334+
1335+
// TODO(fivedots): Figure out mechanism to prevent concurrent IO operations e.g. doing write() while a truncate() is executing in parallel.
13121336
<div algorithm>
1313-
The <dfn method for=FileSystemSyncAccessHandle>write(|buffer|, {{FilesystemReadWriteOptions/at}}: |position|)</dfn> method, when invoked, must run
1337+
The <dfn method for=FileSystemSyncAccessHandle>write(|buffer|, {{FilesystemReadWriteOptions}}: |options|)</dfn> method, when invoked, must run
13141338
these steps:
13151339

1316-
// TODO(fivedots): fill in. Does this algorithm need to explicitly interact with storage quota?
1340+
1. If [=this=].[=[[state]]=] is "closed", throw a {{InvalidStateError}}.
1341+
1. Let |writePosition| be |options|.{{FilesystemReadWriteOptions/at}}.
1342+
1. Let |fileContents| be a copy of [=this=].[=[[file]]=]'s [=file entry/binary data=].
1343+
1. Let |oldSize| be |fileContents|'s [=byte sequence/length=].
1344+
1. Let |data| be [=get a copy of the buffer source|a copy of=] |buffer|.
1345+
1. If |writePosition| is larger than |oldSize|,
1346+
append |writePosition| - |oldSize| `0x00` (NUL) bytes to the end of |fileContents|.
1347+
1348+
Note: Implementations are expected to behave as if the skipped over file contents
1349+
are indeed filled with NUL bytes. That doesn't mean these bytes have to actually be
1350+
written to disk and take up disk space. Instead most file systems support so called
1351+
sparse files, where these NUL bytes don't take up actual disk space.
1352+
1353+
1. Let |head| be a [=byte sequence=] containing the first |writePosition| bytes of |fileContents|.
1354+
1. Let |tail| be an empty [=byte sequence=].
1355+
1. If |writePosition| + |data|.[=byte sequence/length=] is smaller than |oldSize|:
1356+
1. Let |tail| be a [=byte sequence=] containing the last
1357+
|oldSize| - (|writePosition| + |data|.[=byte sequence/length=]) bytes of |fileContents|.
1358+
1. Let |newSize| be the [=byte sequence/length=] of the concatenation of |head|, |data| and |tail|.
1359+
1. If |newSize| - |oldSize| exceeds the available [=storage quota=], throw a {{QuotaExceededError}}.
1360+
1. Set [=this=].[=[[file]]=]'s [=file entry/binary data=] to the concatenation of |head|, |data| and |tail|.
1361+
1. If the operations modifying the [=this=].[=[[file]]=]'s [=file entry/binary data=] in the previous steps
1362+
failed:
1363+
1. If there were partial modifications and the number of modified bytes is known,
1364+
return the number of modified bytes.
1365+
1. Else return 0.
1366+
1. Return |data|.[=byte sequence/length=].
13171367

13181368
</div>
13191369

@@ -1324,6 +1374,7 @@ these steps:
13241374
:: Resizes the file associated with stream to be size bytes long. If size is larger than the current file size this pads the file with null bytes, otherwise it truncates the file.
13251375
</div>
13261376

1377+
//TODO(fivedots):Make sure negative lengths are not allowed.
13271378
<div algorithm>
13281379
The <dfn method for=FileSystemSyncAccessHandle>truncate(|size|)</dfn> method, when invoked, must run
13291380
these steps:
@@ -1351,7 +1402,7 @@ these steps:
13511402

13521403
<div class="note domintro">
13531404
: |handle| . {{FileSystemSyncAccessHandle/flush()}}
1354-
:: Ensures that the contents of the file associated with |handle| contain all the modifications done through {{FileSystemSyncAccessHandle/read()}} and {{FileSystemSyncAccessHandle/write()}}.
1405+
:: Ensures that the contents of the file associated with |handle| contain all the modifications done through {{FileSystemSyncAccessHandle/write()}}.
13551406
</div>
13561407

13571408
<div algorithm>
@@ -1364,19 +1415,22 @@ these steps:
13641415

13651416
### The {{FileSystemSyncAccessHandle/close()}} method ### {#api-filesystemsyncaccesshandle-close}
13661417

1367-
// TODO(fivedots): |fileHandle| is not properly defined here, consider adding an attribute to |handle|.
1368-
13691418
<div class="note domintro">
13701419
: |handle| . {{FileSystemSyncAccessHandle/close()}}
13711420
:: Flushes the access handle and then closes it. Closing an access handle disables any further operations on it and
1372-
[=file entry/lock/release|releases the lock=] on the [=FileSystemHandle/entry=] associated with |fileHandle|.
1421+
[=file entry/lock/release|releases the lock=] on the [=FileSystemHandle/entry=] associated with |handle|.
13731422
</div>
13741423

1424+
//TODO(fivedots): Figure out language to describe flushing the file at the OS level before closing the handle.
13751425
<div algorithm>
13761426
The <dfn method for=FileSystemSyncAccessHandle>close()</dfn> method, when invoked, must run
13771427
these steps:
13781428

1379-
// TODO(fivedots): fill in.
1429+
1. Let |p| be [=a new promise=].
1430+
1. Run the following steps [=in parallel=]:
1431+
1. Set [=this=].[=[[state]]=] to "closed".
1432+
1. [=/Resolve=] |p|.
1433+
1. Return |p|
13801434

13811435
</div>
13821436

0 commit comments

Comments
 (0)