summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/streams/readable-streams/global.html
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/streams/readable-streams/global.html')
-rw-r--r--testing/web-platform/tests/streams/readable-streams/global.html162
1 files changed, 162 insertions, 0 deletions
diff --git a/testing/web-platform/tests/streams/readable-streams/global.html b/testing/web-platform/tests/streams/readable-streams/global.html
new file mode 100644
index 0000000000..08665d318e
--- /dev/null
+++ b/testing/web-platform/tests/streams/readable-streams/global.html
@@ -0,0 +1,162 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Ensure Stream objects are created in expected globals. </title>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<body></body>
+<script>
+// These tests are loosely derived from Gecko's readable-stream-globals.js,
+// which is a test case designed around the JS Streams implementation.
+//
+// Unlike in JS Streams, where function calls switch realms and change
+// the resulting global of the resulting objects, in WebIDL streams,
+// the global of an object is (currently underspecified, but) intended
+// to be the "Relevant Global" of the 'this' object.
+//
+// See:
+// https://html.spec.whatwg.org/multipage/webappapis.html#relevant
+// https://github.com/whatwg/streams/issues/1213
+"use strict"
+
+const iframe = document.createElement("iframe")
+document.body.append(iframe)
+
+const otherGlobal = iframe.contentWindow;
+const OtherReadableStream = otherGlobal.ReadableStream
+const OtherReadableStreamDefaultReader = otherGlobal.ReadableStreamDefaultReader;
+const OtherReadableStreamDefaultController = otherGlobal.ReadableStreamDefaultController;
+
+promise_test(async () => {
+
+ // Controllers
+ let controller;
+ let otherController;
+
+ // Get Stream Prototypes and controllers.
+ let streamController;
+ let stream = new ReadableStream({start(c) { streamController = c; }});
+
+ const callReaderThisGlobal = OtherReadableStream.prototype.getReader.call(stream);
+ const newReaderOtherGlobal = new OtherReadableStreamDefaultReader(new ReadableStream());
+
+ // Relevant Global Checking.
+ assert_equals(callReaderThisGlobal instanceof ReadableStreamDefaultReader, true, "reader was created in this global (.call)");
+ assert_equals(newReaderOtherGlobal instanceof ReadableStreamDefaultReader, false, "reader was created in other global (new)");
+
+ assert_equals(callReaderThisGlobal instanceof OtherReadableStreamDefaultReader, false, "reader isn't coming from other global (.call)" );
+ assert_equals(newReaderOtherGlobal instanceof OtherReadableStreamDefaultReader, true, "reader isn't coming from other global (new)");
+
+ assert_equals(otherController instanceof ReadableStreamDefaultController, false, "otherController should come from other gloal")
+
+
+ const request = callReaderThisGlobal.read();
+ assert_equals(request instanceof Promise, true, "Promise comes from this global");
+
+ streamController.close();
+ const requestResult = await request;
+ assert_equals(requestResult instanceof Object, true, "returned object comes from this global");
+}, "Stream objects created in expected globals")
+
+promise_test(async () => {
+ const stream = new ReadableStream();
+ const otherReader = new OtherReadableStreamDefaultReader(stream);
+ const cancelPromise = ReadableStreamDefaultReader.prototype.cancel.call(otherReader);
+ assert_equals(cancelPromise instanceof Promise, true, "Cancel promise comes from the same global as the stream");
+ assert_equals(await cancelPromise, undefined, "Cancel promise resolves to undefined");
+}, "Cancel promise is created in same global as stream")
+
+// Refresh the streams and controllers.
+function getFreshInstances() {
+ let controller;
+ let otherController;
+ let stream = new ReadableStream({
+ start(c) {
+ controller = c;
+ }
+ });
+
+ new OtherReadableStream({
+ start(c) {
+ otherController = c;
+ }
+ });
+
+ return {stream, controller, otherController}
+}
+
+
+promise_test(async () => {
+ // Test closed promise on reader from another global (connected to a this-global stream)
+ const {stream, controller, otherController} = getFreshInstances();
+
+ const otherReader = new OtherReadableStreamDefaultReader(stream);
+ const closedPromise = otherReader.closed;
+ assert_equals(closedPromise instanceof otherGlobal.Promise, true, "Closed promise in other global.");
+}, "Closed Promise in correct global");
+
+promise_test(async () => {
+ const {stream, controller, otherController} = getFreshInstances();
+
+ const otherReader = OtherReadableStream.prototype.getReader.call(stream);
+ assert_equals(otherReader instanceof ReadableStreamDefaultReader, true, "Reader comes from this global")
+ const request = otherReader.read();
+ assert_equals(request instanceof Promise, true, "Promise still comes from stream's realm (this realm)");
+ otherController.close.call(controller);
+ assert_equals((await request) instanceof otherGlobal.Object, true, "Object comes from other realm");
+}, "Reader objects in correct global");
+
+
+promise_test(async () => {
+ const {stream, controller, otherController} = getFreshInstances();
+ assert_equals(controller.desiredSize, 1, "Desired size is expected");
+ Object.defineProperty(controller, "desiredSize",
+ Object.getOwnPropertyDescriptor(OtherReadableStreamDefaultController.prototype, "desiredSize"));
+ assert_equals(controller.desiredSize, 1, "Grafting getter from other prototype still returns desired size");
+}, "Desired size can be grafted from one prototype to another");
+
+promise_test(async () => {
+ const {stream, controller, otherController} = getFreshInstances();
+
+ // Make sure the controller close method returns the correct TypeError
+ const enqueuedError = { name: "enqueuedError" };
+ controller.error(enqueuedError);
+
+ assert_throws_js(TypeError, () => controller.close(), "Current Global controller");
+ assert_throws_js(otherGlobal.TypeError, () => otherController.close.call(controller), "Other global controller");
+}, "Closing errored stream throws object in appropriate global")
+
+promise_test(async () => {
+ const {otherController} = getFreshInstances();
+ // We can enqueue chunks from multiple globals
+ const chunk = { name: "chunk" };
+
+ let controller;
+ const stream = new ReadableStream({ start(c) { controller = c; } }, { size() {return 1} });
+ otherController.enqueue.call(controller, chunk);
+ otherController.enqueue.call(controller, new otherGlobal.Uint8Array(10));
+ controller.enqueue(new otherGlobal.Uint8Array(10));
+}, "Can enqueue chunks from multiple globals")
+
+promise_test(async () => {
+ const {stream, controller, otherController} = getFreshInstances();
+ const chunk = { name: "chunk" };
+
+ // We get the correct type errors out of a closed stream.
+ controller.close();
+ assert_throws_js(TypeError, () => controller.enqueue(new otherGlobal.Uint8Array(10)));
+ assert_throws_js(otherGlobal.TypeError, () => otherController.enqueue.call(controller, chunk));
+ assert_throws_js(otherGlobal.TypeError, () => otherController.enqueue.call(controller, new otherGlobal.Uint8Array(10)));
+}, "Correct errors and globals for closed streams");
+
+
+promise_test(async () => {
+ const {stream, controller, otherController} = getFreshInstances();
+ // Branches out of tee are in the correct global
+
+ const [branch1, branch2] = otherGlobal.ReadableStream.prototype.tee.call(stream);
+ assert_equals(branch1 instanceof ReadableStream, true, "Branch created in this global (as stream is in this global)");
+ assert_equals(branch2 instanceof ReadableStream, true, "Branch created in this global (as stream is in this global)");
+}, "Tee Branches in correct global");
+</script>