diff --git a/index.bs b/index.bs index 17a5f42..f5b3be5 100644 --- a/index.bs +++ b/index.bs @@ -191,14 +191,14 @@ The requestPermission(|descriptor|) metho ## The {{FileSystemFileHandle}} interface ## {#api-filesystemfilehandle} -dictionary FileSystemCreateWriterOptions { +dictionary FileSystemCreateWritableOptions { boolean keepExistingData = false; }; [Exposed=(Window,Worker), SecureContext, Serializable] interface FileSystemFileHandle : FileSystemHandle { Promise<File> getFile(); - Promise<FileSystemWriter> createWriter(optional FileSystemCreateWriterOptions options = {}); + Promise<FileSystemWritableFileStream> createWritable(optional FileSystemCreateWritableOptions options); }; @@ -223,27 +223,29 @@ The getFile() method, when invoked, m -### The {{FileSystemFileHandle/createWriter()}} method ### {#api-filesystemfilehandle-createwriter} +### The {{FileSystemFileHandle/createWritable()}} method ### {#api-filesystemfilehandle-createwritable} + +Advisement: In the Origin Trial as available in Chrome 82, createWritable replaces the createWriter method.
- : |writer| = await |fileHandle| . {{FileSystemFileHandle/createWriter()}} - : |writer| = await |fileHandle| . {{FileSystemFileHandle/createWriter()|createWriter}}({ {{FileSystemCreateWriterOptions/keepExistingData}}: true/false }) - :: Returns a {{FileSystemWriter}} that can be used to write to the file. Any changes made through - |writer| won't be reflected in the file represented by |fileHandle| until its - {{FileSystemWriter/close()}} method is called. + : |stream| = await |fileHandle| . {{FileSystemFileHandle/createWritable()}} + : |stream| = await |fileHandle| . {{FileSystemFileHandle/createWritable()|createWritable}}({ {{FileSystemCreateWritableOptions/keepExistingData}}: true/false }) + :: Returns a {{FileSystemWritableFileStream}} that can be used to write to the file. Any changes made through + |stream| won't be reflected in the file represented by |fileHandle| until its + {{FileSystemWritableFileStream/close()}} method is called. User agents try to ensure that no partial writes happen, i.e. the file represented by |fileHandle| will either contains its old contents or it will contain whatever data was written - through |writer| up until {{FileSystemWriter/close()}} was called. + through |stream| up until {{FileSystemWritableFileStream/close()}} was called. This is typically implemented by writing data to a temporary file, and only replacing the file - represented by |fileHandle| with the temporary file when the writer is closed. + represented by |fileHandle| with the temporary file when the writable filestream is closed. - If {{FileSystemCreateWriterOptions/keepExistingData}} is `false` or not specified, + If {{FileSystemCreateWritableOptions/keepExistingData}} is `false` or not specified, the temporary file starts out empty, otherwise the existing file is first copied to this temporary file.
-Issue(67): There has been some discussion around and desire for a "inPlace" mode for createWriter +Issue(67): There has been some discussion around and desire for a "inPlace" mode for createWritable (where changes will be written to the actual underlying file as they are written to the writer, for example to support in-place modification of large files or things like databases). This is not currently implemented in Chrome. Implementing this is currently blocked on figuring out how to @@ -251,7 +253,7 @@ combine the desire to run malware checks with the desire to let websites make fa modifications to existing large files.
-The createWriter(|options|) method, when invoked, must run these steps: +The createWritable(|options|) method, when invoked, must run these steps: 1. TODO @@ -405,74 +407,136 @@ these steps:
-## The {{FileSystemWriter}} interface ## {#api-filesystemwriter} +## The {{FileSystemWritableFileStream}} interface ## {#api-filesystemwritablefilestream} -[Exposed=(Window,Worker), SecureContext] -interface FileSystemWriter { - Promise<void> write(unsigned long long position, (BufferSource or Blob or USVString) data); +enum WriteCommandType { + "truncate", + "seek", + "write", +}; + +dictionary WriteParams { + required WriteCommandType type; + unsigned long long? size; + unsigned long long? position; + (BufferSource or Blob or USVString)? data; +}; + +[Exposed=(Window,Worker), SecureContext, Serializable] +interface FileSystemWritableFileStream : WritableStream { + Promise<void> write((BufferSource or Blob or USVString or WriteParams) data); + Promise<void> seek(unsigned long long position); Promise<void> truncate(unsigned long long size); - Promise<void> close(); }; -Issue(19): We want some kind of integration with writable streams. One possible option is to make -FileStreamWriter inherit from WritableStream, but other options should be considered as well. +A {{FileSystemWritableFileStream}} object is a {{WritableStream}} object with additional methods to operate +on a single file on disk. + +Upon creation, an underlying sink will have been created and the stream will be usable. All operations executed on the stream are queuable and producers will be able to respond to backpressure. + +The underlying sink's write method, and therefore {{WritableStreamDefaultWriter/write()|WritableStreamDefaultWriter's write()}} method, will accept byte-like data or {{WriteParams}} as input. + +The {{FileSystemWritableFileStream}} has a file position cursor initialized at byte offset 0 from the top of the file. When using {{FileSystemWritableFileStream/write()|write()}} or by using WritableStream capabilities through the {{WritableStreamDefaultWriter/write()|WritableStreamDefaultWriter's write()}} method, this position will be advanced based on the number of bytes written through the stream object. + +Similarly, when piping a {{ReadableStream}} into a {{FileSystemWritableFileStream}} object, this position is updated with the number of bytes that passed through the stream. -### The {{FileSystemWriter/write()}} method ### {#api-filesystemwriter-write} +{{WritableStream/getWriter()|getWriter()}} returns an instance of {{WritableStreamDefaultWriter}}. + +
+{{FileSystemWritableFileStream}} objects are [=serializable objects=]. They not cloneable, i.e. they are transferable-only, as are {{WritableStream}} objects. + +Advisement: In the Origin Trial as available in Chrome 82, these objects are not yet serializable. + +Their [=serialization steps=], given |value|, |serialized| and |forStorage| are: + +1. Set |serialized|.\[[Origin]] to |value|'s [=relevant settings object=]'s [=environment settings object/origin=]. +1. TODO + +
+ +
+Their [=deserialization steps=], given |serialized| and |value| are: + +1. If |serialized|.\[[Origin]] is not [=same origin=] with + |value|'s [=relevant settings object=]'s [=environment settings object/origin=], + then throw a {{DataCloneError}}. +1. TODO + +
+ +### The {{FileSystemWritableFileStream/write()}} method ### {#api-filesystemwritablefilestream-write}
- : await |writer| . {{FileSystemWriter/write()|write}}(|position|, |data|) - :: Writes the content of |data| into the file associated with |writer| at position |position|. - If |position| is past the end of the file writing will fail and this method rejects. + : await |stream| . {{FileSystemWritableFileStream/write()|write}}(|data|) + :: Writes the content of |data| into the file associated with |stream| at the current file + cursor offset in bytes from the top of the file by default. - No changes are written to the actual file until on disk until {{FileSystemWriter/close()}} + No changes are written to the actual file until on disk until {{FileSystemWritableFileStream/close()}} + is called. Changes are typically written to a temporary file instead. + + If |data| is of type {{WriteParams}}, validates and executes the content of |data|, which might result in changes into the file associated with |stream|. + + {{WriteParams}} requires the attribute {{WriteParams/type|type}} which determines what the operations to + execute are. + + If {{WriteParams/type|type}} is {{truncate}}, {{WriteParams/size|size}} is a required attribute. + + If {{WriteParams/type|type}} is {{seek}}, {{WriteParams/position|position}} is a required attribute. + + If {{WriteParams/type|type}} is {{write}}, {{WriteParams/position|position}} is an optional attribute, {{WriteParams/data|data}} is a required attribute. + + No changes are written to the actual file until on disk until {{FileSystemWritableFileStream/close()}} is called. Changes are typically written to a temporary file instead.
-The write(|position|, |data|) method, when invoked, must run +The write(|data|) method, when invoked, must run these steps: 1. TODO
-### The {{FileSystemWriter/truncate()}} method ### {#api-filesystemwriter-truncate} +### The {{FileSystemWritableFileStream/truncate()}} method ### {#api-filesystemwritablefilestream-truncate}
- : await |writer| . {{FileSystemWriter/truncate()|truncate}}(|size|) - :: Resizes the file associated with |writer| to be |size| bytes long. If |size| is larger than + : await |stream| . {{FileSystemWritableFileStream/truncate()|truncate}}(|size|) + :: 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. - No changes are written to the actual file until on disk until {{FileSystemWriter/close()}} + The file cursor is updated when {{truncate}} is called. If the offset is smaller than offset, + it remains unchanged. If the offset is larger than |size|, the offset is set to |size| to + ensure that subsequent writes do not error. + + No changes are written to the actual file until on disk until {{FileSystemWritableFileStream/close()}} is called. Changes are typically written to a temporary file instead.
-The truncate(|size|) method, when invoked, must run these +The truncate(|size|) method, when invoked, must run these steps: 1. TODO
-### The {{FileSystemWriter/close()}} method ### {#api-filesystemwriter-close} +### The {{FileSystemWritableFileStream/close()}} method ### {#api-filesystemwritablefilestream-close}
- : await |writer| . {{FileSystemWriter/close()}} - :: First flushes any data written so far to disk, and then closes the writer. + : await |stream| . {{FileSystemWritableFileStream/close()}} + :: First flushes any data written so far to disk, and then closes the writable stream. No changes will be visible in the destination file until this method is called. - Furthermore, if the file on disk changed between creating this |writer| and this invocation of - {{FileSystemWriter/close()}}, this will reject and all future operations on the writer will - fail. + Furthermore, if the file on disk changed between creating this |stream| and this invocation of + {{FileSystemWritableFileStream/close()}}, this will reject and all future operations on the stream will fail. This operation can take some time to complete, as user agents might use this moment to run malware scanners or perform other security checks if the website isn't sufficiently trusted.
-The close() method, when invoked, must run these +The close() method, when invoked, must run these steps: 1. TODO