- From: Takeshi Yoshino <tyoshino@google.com>
- Date: Wed, 11 Sep 2013 23:24:47 +0900
- To: Isaac Schlueter <i@izs.me>
- Cc: Aymeric Vitte <vitteaymeric@gmail.com>, Jonas Sicking <jonas@sicking.cc>, Austin William Wright <aaa@bzfx.net>, Domenic Denicola <domenic@domenicdenicola.com>, "public-webapps@w3.org" <public-webapps@w3.org>
- Message-ID: <CAH9hSJZ9DvyGomLMoWpC9nQNWBe6o+Oyo-p87E1D37-hK5eKiA@mail.gmail.com>
Here's my all-in-one strawman proposal including some new stuff for flow control. Yes, it's too big, but may be useful for glancing what features are requested. ==== enum StreamReadType { "", "arraybuffer", "text" }; [Constructor(optional DOMString mime, optional [Clamp] long long writeBufferSize, optional [Clamp] long long readBufferSize)] interface Stream : EventTarget { readonly attribute DOMString type; // MIME type // Writing interfaces readonly attribute unsigned long long writableSize; // Bytes can be written synchronously attribute unsigned long long writeBufferSize; attribute EventHandler onwritable; attribute unsigned long long writableThreshold; attribute EventHandler onpulled; attribute EventHandler onreadaborted; void write((DOMString or ArrayBufferView or Blob)? data); void flush(); void closeWrite(); void abortWrite(); // Reading interfaces attribute StreamReadType readType; // Must not be set after the first read() attribute DOMString readEncoding; readonly attribute unsigned long long readableSize; // Bytes can be read synchronously attribute unsigned long long readBufferSize; attribute EventHandler onreadable; attribute unsigned long long readableThreshold; attribute EventHandler onflush; attribute EventHandler onclose; // Receives clean flag any read(optional [Clamp] long long size); any peek(optional [Clamp] long long size, optional [Clamp] long long offset); void skip([Clamp] long long size); void pull(); void abortRead(); // Async interfaces attribute EventHandler ondoneasync; // Receives bytes skipped or Blob or undefined (when done pipeTo) void readAsBlob(optional [Clamp] long long size); void longSkip([Clamp] long long size); void pipeTo(Stream destination, optional [Clamp] long long size); }; ==== - Encoding for text mode reading is determined by the type attribute. Can be overridden by setting the readEncoding attribute. - Invoking read() repeatedly to pull data into the stream is annoying. So, instead I used writable/readableThreshold approach. - Not to bloat the API anymore, limited error/close signaling interface to only EventHandlers. - stream.read() means stream.read(stream.readableSize). - After onclose invocation, it's guaranteed that all written bytes are available for read. - read() is non-blocking. It returns only what is synchronously readable. If there isn't enough bytes (investigate the readableSize attribute), an app should wait until the next invocation of onreadable. readBufferSize and readableThreshold may be modified accordingly and pull() may be called. - stream.read(size) returns an ArrayBuffer or DOMString of min(size, stream.readableSize) bytes that is synchronously readable now. - When readType is set to "text", read() throws an "EncodingError" if an invalid sequence is found. Incomplete sequence will be left unconsumed. If there's an incomplete sequence at the end of stream, the app can know that by checking the size attribute after onclose invocation and read() call. - readableSize attribute returns (number of readable bytes as of the last time the event loop started executing a task) - (bytes consumed by read() method). - onflush is separated from onreadable since it's possible that an intermediate Stream in a long change has no data to flush but the next or later Streams have. - Invocation order is onreadable -> onflush or onclose. - Flush handling code must be implemented on both onflush and onclose. On close() call, only onclose is invoked to reduce event propagation cost. - Pass read/writeBufferSize of -1 to constructor or set -1 to stream.read/writeBufferSize for unlimited buffering. - Instead of having write(buffer, cb), made write() accept any size of data regardless of writeBufferSize. XHR should respect writeBufferSize and write only writableSize bytes of data and set onwritable if necessary and possibly also set writableThreashold. - {writable,readable}Threshold are 0 by default meaning that onwritable and onreadable are invoked immediately when there's space/data available. - If {writable,readable}Threshold are greater than capacity, it's considered to be set to capacity. - onwritable/onreadable is invoked asynchronously when -- new space/data is available as a result of read()/write() operation that satisfies writable/readableThreshold onreadable is invoked asynchronously when -- flush()-ed or close()-ed - onwritable/onreadable is invoked synchronously when -- onwritable/onreadable is updated and there's space/data available that satisfies writable/readableThreshold -- writable/readableThreshold is updated and there's space/data available that satisfies the new writable/readableThreshold -- new space/data is available as a result of updating capacity that satisfies writable/readableThreshold
Received on Wednesday, 11 September 2013 14:25:35 UTC