Commit 06c431ff authored by Adam Rice's avatar Adam Rice Committed by Commit Bot

Add spec references for transferable streams

Now that the standard changes for transferable streams have landed, add
comments to the source referencing the spec.

No functional changes.

BUG=894838

Change-Id: I3107c62a361257fb6bad81f45e6d108de4a74622
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2359812Reviewed-by: default avatarYutaka Hirano <yhirano@chromium.org>
Commit-Queue: Adam Rice <ricea@chromium.org>
Cr-Commit-Position: refs/heads/master@{#798972}
parent f4cc5f52
......@@ -456,9 +456,18 @@ void SerializedScriptValue::TransferTransformStreams(
// a MessagePortChannel, and returns the other end as a MessagePort.
MessagePort* SerializedScriptValue::AddStreamChannel(
ExecutionContext* execution_context) {
// Used for both https://streams.spec.whatwg.org/#rs-transfer and
// https://streams.spec.whatwg.org/#ws-transfer.
// 2. Let port1 be a new MessagePort in the current Realm.
// 3. Let port2 be a new MessagePort in the current Realm.
MessagePortDescriptorPair pipe;
auto* local_port = MakeGarbageCollected<MessagePort>(*execution_context);
// 4. Entangle port1 and port2.
local_port->Entangle(pipe.TakePort0());
// 9. Set dataHolder.[[port]] to ! StructuredSerializeWithTransfer(port2,
// « port2 »).
stream_channels_.push_back(MessagePortChannel(pipe.TakePort1()));
return local_port;
}
......
......@@ -580,18 +580,30 @@ ScriptWrappable* V8ScriptValueDeserializer::ReadDOMObject(
index + 1 >= transferred_stream_ports_->size()) {
return nullptr;
}
// https://streams.spec.whatwg.org/#ts-transfer
// 1. Let readableRecord be !
// StructuredDeserializeWithTransfer(dataHolder.[[readable]], the
// current Realm).
ReadableStream* readable = ReadableStream::Deserialize(
script_state_, (*transferred_stream_ports_)[index].Get(),
exception_state);
if (!readable)
return nullptr;
// 2. Let writableRecord be !
// StructuredDeserializeWithTransfer(dataHolder.[[writable]], the
// current Realm).
WritableStream* writable = WritableStream::Deserialize(
script_state_, (*transferred_stream_ports_)[index + 1].Get(),
exception_state);
if (!writable)
return nullptr;
// 3. Set value.[[readable]] to readableRecord.[[Deserialized]].
// 4. Set value.[[writable]] to writableRecord.[[Deserialized]].
// 5. Set value.[[backpressure]], value.[[backpressureChangePromise]], and
// value.[[controller]] to undefined.
return MakeGarbageCollected<TransformStream>(readable, writable);
}
case kDOMExceptionTag: {
......
......@@ -580,6 +580,11 @@ bool V8ScriptValueSerializer::WriteDOMObject(ScriptWrappable* wrappable,
"because it was not transferred.");
return false;
}
// https://streams.spec.whatwg.org/#ts-transfer
// 3. If ! IsReadableStreamLocked(readable) is true, throw a
// "DataCloneError" DOMException.
// 4. If ! IsWritableStreamLocked(writable) is true, throw a
// "DataCloneError" DOMException.
if (stream->Readable()->locked() || stream->Writable()->locked()) {
exception_state.ThrowDOMException(
DOMExceptionCode::kDataCloneError,
......
......@@ -1606,20 +1606,38 @@ void ReadableStream::LockAndDisturb(ScriptState* script_state) {
void ReadableStream::Serialize(ScriptState* script_state,
MessagePort* port,
ExceptionState& exception_state) {
// https://streams.spec.whatwg.org/#rs-transfer
// 1. If ! IsReadableStreamLocked(value) is true, throw a "DataCloneError"
// DOMException.
if (IsLocked(this)) {
exception_state.ThrowTypeError("Cannot transfer a locked stream");
return;
}
// Done by SerializedScriptValue::TransferReadableStream():
// 2. Let port1 be a new MessagePort in the current Realm.
// 3. Let port2 be a new MessagePort in the current Realm.
// 4. Entangle port1 and port2.
// 5. Let writable be a new WritableStream in the current Realm.
// 6. Perform ! SetUpCrossRealmTransformWritable(writable, port1).
auto* writable =
CreateCrossRealmTransformWritable(script_state, port, exception_state);
if (exception_state.HadException()) {
return;
}
// 7. Let promise be ! ReadableStreamPipeTo(value, writable, false, false,
// false).
auto promise =
PipeTo(script_state, this, writable, MakeGarbageCollected<PipeOptions>());
// 8. Set promise.[[PromiseIsHandled]] to true.
promise.MarkAsHandled();
// This step is done in a roundabout way by the caller:
// 9. Set dataHolder.[[port]] to ! StructuredSerializeWithTransfer(port2,
// « port2 »).
}
ReadableStream* ReadableStream::Deserialize(ScriptState* script_state,
......@@ -1629,6 +1647,17 @@ ReadableStream* ReadableStream::Deserialize(ScriptState* script_state,
// run author code.
v8::Isolate::AllowJavascriptExecutionScope allow_js(
script_state->GetIsolate());
// https://streams.spec.whatwg.org/#rs-transfer
// These steps are done by V8ScriptValueDeserializer::ReadDOMObject().
// 1. Let deserializedRecord be !
// StructuredDeserializeWithTransfer(dataHolder.[[port]], the current
// Realm).
// 2. Let port be deserializedRecord.[[Deserialized]].
// 3. Perform ! SetUpCrossRealmTransformReadable(value, port).
// In the standard |value| contains an uninitialized ReadableStream. In the
// implementation, we create the stream here.
auto* readable =
CreateCrossRealmTransformReadable(script_state, port, exception_state);
if (exception_state.HadException()) {
......
......@@ -20,12 +20,16 @@ class WritableStream;
// Creates the writable side of a cross-realm identity transform stream, using
// |port| for communication. |port| must be entangled with another MessagePort
// which is passed to CreateCrossRealmTransformReadable().
// Equivalent to SetUpCrossRealmTransformWritable in the standard:
// https://streams.spec.whatwg.org/#abstract-opdef-setupcrossrealmtransformwritable
CORE_EXPORT WritableStream* CreateCrossRealmTransformWritable(ScriptState*,
MessagePort* port,
ExceptionState&);
// Creates the readable side of a cross-realm identity transform stream. |port|
// is used symmetrically with CreateCrossRealmTransformWritable().
// Equivalent to SetUpCrossRealmTransformReadable in the standard:
// https://streams.spec.whatwg.org/#abstract-opdef-setupcrossrealmtransformreadable
CORE_EXPORT ReadableStream* CreateCrossRealmTransformReadable(ScriptState*,
MessagePort* port,
ExceptionState&);
......
......@@ -225,21 +225,39 @@ WritableStream* WritableStream::CreateWithCountQueueingStrategy(
void WritableStream::Serialize(ScriptState* script_state,
MessagePort* port,
ExceptionState& exception_state) {
// https://streams.spec.whatwg.org/#ws-transfer
// 1. If ! IsWritableStreamLocked(value) is true, throw a "DataCloneError"
// DOMException.
if (IsLocked(this)) {
exception_state.ThrowTypeError("Cannot transfer a locked stream");
return;
}
// Done by SerializedScriptValue::TransferWritableStream():
// 2. Let port1 be a new MessagePort in the current Realm.
// 3. Let port2 be a new MessagePort in the current Realm.
// 4. Entangle port1 and port2.
// 5. Let readable be a new ReadableStream in the current Realm.
// 6. Perform ! SetUpCrossRealmTransformReadable(readable, port1).
auto* readable =
CreateCrossRealmTransformReadable(script_state, port, exception_state);
if (exception_state.HadException()) {
return;
}
// 7. Let promise be ! ReadableStreamPipeTo(readable, value, false, false,
// false).
auto promise = ReadableStream::PipeTo(
script_state, readable, this,
MakeGarbageCollected<ReadableStream::PipeOptions>());
// 8. Set promise.[[PromiseIsHandled]] to true.
promise.MarkAsHandled();
// This step is done in a roundabout way by the caller:
// 9. Set dataHolder.[[port]] to ! StructuredSerializeWithTransfer(port2, «
// port2 »).
}
WritableStream* WritableStream::Deserialize(ScriptState* script_state,
......@@ -249,6 +267,17 @@ WritableStream* WritableStream::Deserialize(ScriptState* script_state,
// run author code.
v8::Isolate::AllowJavascriptExecutionScope allow_js(
script_state->GetIsolate());
// https://streams.spec.whatwg.org/#ws-transfer
// These step is done by V8ScriptValueDeserializer::ReadDOMObject().
// 1. Let deserializedRecord be !
// StructuredDeserializeWithTransfer(dataHolder.[[port]], the current
// Realm).
// 2. Let port be deserializedRecord.[[Deserialized]].
// 3. Perform ! SetUpCrossRealmTransformWritable(value, port).
// In the standard |value| contains an unitialized WritableStream. In the
// implementation, we create the stream here.
auto* writable =
CreateCrossRealmTransformWritable(script_state, port, exception_state);
if (exception_state.HadException()) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment