forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement serialization of ReadableStream
Enable ReadableStream objects to be transferred by postMessage(). Internally, the ReadableStream is converted to a MessagePortChannel and it is that that is transferred. This involves adding a "stream_channels" field to the TransferableMessage mojo struct for the channels that will be used by ReadableStream (and in future WritableStream and TransferableStream objects). Additional code is added to V8ScriptValueSerializer and V8ScriptValueDeserializer to recognise ReadableStream objects. SerializedScriptValue has new methods and an array of MessagePortChannels as a member variable to transfer them. The new code is behind the "TransferableStreams" Blink feature and must be explicitly activated. A set of new layout tests provides basic verification that postMessage() of ReadableStream objects work. They are run with the feature enabled via a new VirtualTestSuite. The changes are covered in more detail in the design doc: https://docs.google.com/document/d/1_KuZzg5c3pncLJPFa8SuVm23AP4tft6mzPCL5at3I9M/edit Bug: 894838 Cq-Include-Trybots: luci.chromium.try:linux_mojo Change-Id: I032306415aa0c4e146af25439f42bcff70436416 Reviewed-on: https://chromium-review.googlesource.com/c/1315367 Commit-Queue: Adam Rice <ricea@chromium.org> Reviewed-by: Yuki Shiino <yukishiino@chromium.org> Reviewed-by: Jeremy Roman <jbroman@chromium.org> Reviewed-by: Kinuko Yasuda <kinuko@chromium.org> Reviewed-by: Yutaka Hirano <yhirano@chromium.org> Cr-Commit-Position: refs/heads/master@{#609688}
- Loading branch information
Showing
43 changed files
with
592 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
third_party/WebKit/LayoutTests/http/tests/streams/transferable/resources/echo-iframe.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<!DOCTYPE html> | ||
<meta charset="utf-8"> | ||
<script> | ||
addEventListener('message', evt => { | ||
evt.source.postMessage(evt.data, '*', [evt.data]); | ||
}); | ||
</script> |
81 changes: 81 additions & 0 deletions
81
third_party/WebKit/LayoutTests/http/tests/streams/transferable/resources/helpers.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// Create a ReadableStream that will pass the tests in | ||
// testTransferredReadableStream(), below. | ||
function createOriginalReadableStream() { | ||
return new ReadableStream({ | ||
start(controller) { | ||
controller.enqueue('a'); | ||
controller.close(); | ||
} | ||
}); | ||
} | ||
|
||
// Common tests to roughly determine that |rs| is a correctly transferred | ||
// version of a stream created by createOriginalReadableStream(). | ||
function testTransferredReadableStream(rs) { | ||
assert_equals(rs.constructor, ReadableStream, | ||
'rs should be a ReadableStream in this realm'); | ||
assert_true(rs instanceof ReadableStream, | ||
'instanceof check should pass'); | ||
|
||
// Perform a brand-check on |rs| in the process of calling getReader(). | ||
const reader = ReadableStream.prototype.getReader.call(rs); | ||
|
||
return reader.read().then(({value, done}) => { | ||
assert_false(done, 'done should be false'); | ||
assert_equals(value, 'a', 'value should be "a"'); | ||
return reader.read(); | ||
}).then(({value, done}) => { | ||
assert_true(done, 'done should be true'); | ||
}); | ||
} | ||
|
||
function testMessage(msg) { | ||
assert_array_equals(msg.ports, [], 'there should be no ports in the event'); | ||
return testTransferredReadableStream(msg.data); | ||
} | ||
|
||
function testMessageEvent(target) { | ||
return new Promise((resolve, reject) => { | ||
target.addEventListener('message', ev => { | ||
try { | ||
resolve(testMessage(ev)); | ||
} catch(e) { | ||
reject(e); | ||
} | ||
}, {once: true}); | ||
}); | ||
} | ||
|
||
function testMessageEventOrErrorMessage(target) { | ||
return new Promise((resolve, reject) => { | ||
target.addEventListener('message', ev => { | ||
if (typeof ev.data === 'string') { | ||
// Assume it's an error message and reject with it. | ||
reject(ev.data); | ||
return; | ||
} | ||
|
||
try { | ||
resolve(testMessage(ev)); | ||
} catch(e) { | ||
reject(e); | ||
} | ||
}, {once: true}); | ||
}); | ||
} | ||
|
||
function checkTestResults(target) { | ||
return new Promise((resolve, reject) => { | ||
target.onmessage = msg => { | ||
// testharness.js sends us objects which we need to ignore. | ||
if (typeof msg.data !== 'string') | ||
return; | ||
|
||
if (msg.data === 'OK') { | ||
resolve(); | ||
} else { | ||
reject(msg.data); | ||
} | ||
}; | ||
}); | ||
} |
11 changes: 11 additions & 0 deletions
11
...y/WebKit/LayoutTests/http/tests/streams/transferable/resources/receiving-shared-worker.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
'use strict'; | ||
importScripts('/resources/testharness.js', 'helpers.js'); | ||
|
||
onconnect = evt => { | ||
const port = evt.source; | ||
const promise = testMessageEvent(port); | ||
port.start(); | ||
promise | ||
.then(() => port.postMessage('OK')) | ||
.catch(err => port.postMessage(`BAD: ${err}`)); | ||
}; |
7 changes: 7 additions & 0 deletions
7
third_party/WebKit/LayoutTests/http/tests/streams/transferable/resources/receiving-worker.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
'use strict'; | ||
importScripts('/resources/testharness.js', 'helpers.js'); | ||
|
||
const promise = testMessageEvent(self); | ||
promise | ||
.then(() => postMessage('OK')) | ||
.catch(err => postMessage(`BAD: ${err}`)); |
12 changes: 12 additions & 0 deletions
12
...rty/WebKit/LayoutTests/http/tests/streams/transferable/resources/sending-shared-worker.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
'use strict'; | ||
importScripts('helpers.js'); | ||
|
||
onconnect = msg => { | ||
const port = msg.source; | ||
const orig = createOriginalReadableStream(); | ||
try { | ||
port.postMessage(orig, [orig]); | ||
} catch (e) { | ||
port.postMessage(e.message); | ||
} | ||
}; |
5 changes: 5 additions & 0 deletions
5
third_party/WebKit/LayoutTests/http/tests/streams/transferable/resources/sending-worker.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
'use strict'; | ||
importScripts('helpers.js'); | ||
|
||
const orig = createOriginalReadableStream(); | ||
postMessage(orig, [orig]); |
39 changes: 39 additions & 0 deletions
39
...y/WebKit/LayoutTests/http/tests/streams/transferable/resources/service-worker-iframe.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<!DOCTYPE html> | ||
<meta charset="utf-8"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="helpers.js"></script> | ||
<script> | ||
'use strict'; | ||
|
||
setup({ | ||
explicit_done: true | ||
}); | ||
|
||
function startTests() { | ||
promise_test(() => { | ||
const orig = createOriginalReadableStream(); | ||
const promise = checkTestResults(navigator.serviceWorker); | ||
navigator.serviceWorker.controller.postMessage(orig, [orig]); | ||
assert_true(orig.locked, 'the original stream should be locked'); | ||
return promise; | ||
}, 'serviceWorker.controller.postMessage should be able to transfer a ' + | ||
'ReadableStream'); | ||
|
||
promise_test(() => { | ||
const promise = testMessageEventOrErrorMessage(navigator.serviceWorker); | ||
navigator.serviceWorker.controller.postMessage('SEND'); | ||
return promise; | ||
}, 'postMessage in a service worker should be able to transfer ReadableStream'); | ||
|
||
done(); | ||
} | ||
|
||
// Delay running the tests until we get a message from the page telling us to. | ||
// This is to work around an issue where testharness.js doesn't detect | ||
// completion of the tests if they fail too early. | ||
onmessage = msg => { | ||
if (msg.data === 'explicit trigger') | ||
startTests(); | ||
}; | ||
|
||
</script> |
30 changes: 30 additions & 0 deletions
30
third_party/WebKit/LayoutTests/http/tests/streams/transferable/resources/service-worker.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
'use strict'; | ||
importScripts('/resources/testharness.js', 'helpers.js'); | ||
|
||
onmessage = msg => { | ||
const client = msg.source; | ||
if (msg.data === 'SEND') { | ||
sendingTest(client); | ||
} else { | ||
receivingTest(msg, client); | ||
} | ||
}; | ||
|
||
function sendingTest(client) { | ||
const orig = createOriginalReadableStream(); | ||
try { | ||
client.postMessage(orig, [orig]); | ||
} catch (e) { | ||
client.postMessage(e.message); | ||
} | ||
} | ||
|
||
function receivingTest(msg, client) { | ||
try { | ||
msg.waitUntil(testMessage(msg) | ||
.then(() => client.postMessage('OK')) | ||
.catch(e => client.postMessage(`BAD: ${e}`))); | ||
} catch (e) { | ||
client.postMessage(`BAD: ${e}`); | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
third_party/WebKit/LayoutTests/http/tests/streams/transferable/service-worker-expected.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
This is a testharness.js-based test. | ||
PASS service-worker | ||
FAIL serviceWorker.controller.postMessage should be able to transfer a ReadableStream Failed to execute 'postMessage' on 'ServiceWorker': Value at index 0 does not have a transferable type. | ||
FAIL postMessage in a service worker should be able to transfer ReadableStream promise_test: Unhandled rejection with value: "Failed to execute 'postMessage' on 'Client': Value at index 0 does not have a transferable type." | ||
Harness: the test ran to completion. | ||
|
29 changes: 29 additions & 0 deletions
29
third_party/WebKit/LayoutTests/http/tests/streams/transferable/service-worker.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<!DOCTYPE html> | ||
<meta charset="utf-8"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script src="/serviceworker/resources/test-helpers.js"></script> | ||
<script> | ||
'use strict'; | ||
|
||
const kServiceWorkerUrl = 'resources/service-worker.js'; | ||
const kIframeUrl = 'resources/service-worker-iframe.html'; | ||
|
||
// A dummy test so that we can use the test-helpers.js functions | ||
const test = async_test('service-worker'); | ||
|
||
function registerAndStart() { | ||
return service_worker_unregister_and_register( | ||
test, kServiceWorkerUrl, kIframeUrl) | ||
.then(reg => wait_for_state(test, reg.installing, 'activated')) | ||
.then(() => with_iframe(kIframeUrl, { auto_remove: true })) | ||
.then(iframe => { | ||
fetch_tests_from_window(iframe.contentWindow); | ||
iframe.contentWindow.postMessage('explicit trigger', '*'); | ||
return service_worker_unregister_and_done(test, kIframeUrl); | ||
}); | ||
} | ||
|
||
onload = registerAndStart; | ||
|
||
</script> |
5 changes: 5 additions & 0 deletions
5
third_party/WebKit/LayoutTests/http/tests/streams/transferable/shared-worker-expected.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
This is a testharness.js-based test. | ||
FAIL worker.postMessage should be able to transfer a ReadableStream Failed to execute 'postMessage' on 'MessagePort': Value at index 0 does not have a transferable type. | ||
FAIL postMessage in a worker should be able to transfer a ReadableStream promise_test: Unhandled rejection with value: "Failed to execute 'postMessage' on 'MessagePort': Value at index 0 does not have a transferable type." | ||
Harness: the test ran to completion. | ||
|
25 changes: 25 additions & 0 deletions
25
third_party/WebKit/LayoutTests/http/tests/streams/transferable/shared-worker.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<!DOCTYPE html> | ||
<meta charset="utf-8"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script src="resources/helpers.js"></script> | ||
<script> | ||
'use strict'; | ||
|
||
promise_test(t => { | ||
const orig = createOriginalReadableStream(); | ||
const w = new SharedWorker('resources/receiving-shared-worker.js'); | ||
const promise = checkTestResults(w.port); | ||
w.port.postMessage(orig, [orig]); | ||
assert_true(orig.locked, 'the original stream should be locked'); | ||
return promise; | ||
}, 'worker.postMessage should be able to transfer a ReadableStream'); | ||
|
||
promise_test(t => { | ||
const w = new SharedWorker('resources/sending-shared-worker.js'); | ||
const promise = testMessageEventOrErrorMessage(w.port); | ||
w.port.start(); | ||
return promise; | ||
}, 'postMessage in a worker should be able to transfer a ReadableStream'); | ||
|
||
</script> |
10 changes: 10 additions & 0 deletions
10
third_party/WebKit/LayoutTests/http/tests/streams/transferable/window-expected.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
CONSOLE ERROR: line 43: Uncaught (in promise) Error: assert_array_equals: there should be no ports in the event lengths differ, expected 0 got 1 | ||
CONSOLE ERROR: line 43: Uncaught (in promise) Error: assert_array_equals: there should be no ports in the event lengths differ, expected 0 got 1 | ||
This is a testharness.js-based test. | ||
Harness Error. harness_status.status = 1 , harness_status.message = assert_array_equals: there should be no ports in the event lengths differ, expected 0 got 1 | ||
FAIL window.postMessage should be able to transfer a ReadableStream Failed to execute 'postMessage' on 'Window': Value at index 0 does not have a transferable type. | ||
FAIL port.postMessage should be able to transfer a ReadableStream Failed to execute 'postMessage' on 'MessagePort': Value at index 0 does not have a transferable type. | ||
FAIL the same ReadableStream posted multiple times should arrive together Failed to execute 'postMessage' on 'Window': Value at index 0 does not have a transferable type. | ||
FAIL transfer to and from an iframe should work promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'postMessage' on 'Window': Value at index 0 does not have a transferable type." | ||
Harness: the test ran to completion. | ||
|
60 changes: 60 additions & 0 deletions
60
third_party/WebKit/LayoutTests/http/tests/streams/transferable/window.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
<!DOCTYPE html> | ||
<meta charset="utf-8"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script src="resources/helpers.js"></script> | ||
<script> | ||
'use strict'; | ||
|
||
promise_test(t => { | ||
const orig = createOriginalReadableStream(); | ||
const promise = testMessageEvent(window); | ||
postMessage(orig, '*', [orig]); | ||
assert_true(orig.locked, 'the original stream should be locked'); | ||
return promise; | ||
}, 'window.postMessage should be able to transfer a ReadableStream'); | ||
|
||
promise_test(t => { | ||
const orig = createOriginalReadableStream(); | ||
const promise = new Promise(resolve => { | ||
window.addEventListener('message', msg => { | ||
const port = msg.data; | ||
resolve(testMessageEvent(port)); | ||
port.start(); | ||
}, {once: true}); | ||
}); | ||
const mc = new MessageChannel(); | ||
postMessage(mc.port1, '*', [mc.port1]); | ||
mc.port2.postMessage(orig, [orig]); | ||
mc.port2.close(); | ||
assert_true(orig.locked, 'the original stream should be locked'); | ||
return promise; | ||
}, 'port.postMessage should be able to transfer a ReadableStream'); | ||
|
||
promise_test(t => { | ||
const orig = createOriginalReadableStream(); | ||
const promise = new Promise(resolve => { | ||
addEventListener('message', t.step_func(evt => { | ||
const [rs1, rs2] = evt.data; | ||
assert_equals(rs1, rs2, 'both ReadableStreams should be the same object'); | ||
resolve(); | ||
}), {once: true}); | ||
}); | ||
postMessage([orig, orig], '*', [orig]); | ||
return promise; | ||
}, 'the same ReadableStream posted multiple times should arrive together'); | ||
|
||
const onloadPromise = new Promise(resolve => onload = resolve); | ||
|
||
promise_test(() => { | ||
const orig = createOriginalReadableStream(); | ||
const promise = testMessageEvent(window); | ||
return onloadPromise.then(() => { | ||
const echoIframe = document.querySelector('#echo'); | ||
echoIframe.contentWindow.postMessage(orig, '*', [orig]); | ||
return promise; | ||
}); | ||
}, 'transfer to and from an iframe should work'); | ||
</script> | ||
|
||
<iframe id=echo src="resources/echo-iframe.html" style="display:none"></iframe> |
6 changes: 6 additions & 0 deletions
6
third_party/WebKit/LayoutTests/http/tests/streams/transferable/worker-expected.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
CONSOLE ERROR: line 5: Uncaught TypeError: Failed to execute 'postMessage' on 'DedicatedWorkerGlobalScope': Value at index 0 does not have a transferable type. | ||
This is a testharness.js-based test. | ||
FAIL worker.postMessage should be able to transfer a ReadableStream Failed to execute 'postMessage' on 'Worker': Value at index 0 does not have a transferable type. | ||
FAIL postMessage in a worker should be able to transfer a ReadableStream promise_test: Unhandled rejection with value: "error in worker" | ||
Harness: the test ran to completion. | ||
|
Oops, something went wrong.