summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/dom/observable/tentative/observable-constructor.window.js
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/dom/observable/tentative/observable-constructor.window.js')
-rw-r--r--testing/web-platform/tests/dom/observable/tentative/observable-constructor.window.js127
1 files changed, 127 insertions, 0 deletions
diff --git a/testing/web-platform/tests/dom/observable/tentative/observable-constructor.window.js b/testing/web-platform/tests/dom/observable/tentative/observable-constructor.window.js
new file mode 100644
index 0000000000..d2b597c819
--- /dev/null
+++ b/testing/web-platform/tests/dom/observable/tentative/observable-constructor.window.js
@@ -0,0 +1,127 @@
+async function loadIframeAndReturnContentWindow() {
+ // Create and attach an iframe.
+ const iframe = document.createElement('iframe');
+ const iframeLoadPromise = new Promise((resolve, reject) => {
+ iframe.onload = resolve;
+ iframe.onerror = reject;
+ });
+ document.body.append(iframe);
+ await iframeLoadPromise;
+ return iframe.contentWindow;
+}
+
+promise_test(async t => {
+ // Hang this off of the main document's global, so the child can easily reach
+ // it.
+ window.results = [];
+ const contentWin = await loadIframeAndReturnContentWindow();
+
+ contentWin.eval(`
+ // Get a reference to the parent result array before we detach and lose
+ // access to the parent.
+ const parentResults = parent.results;
+
+ const source = new Observable((subscriber) => {
+ parentResults.push("subscribe");
+ // Detach the iframe and push a value to the subscriber/Observer.
+ window.frameElement.remove();
+ parentResults.push("detached");
+ subscriber.next("next");
+ subscriber.complete();
+ subscriber.error("error");
+ });
+ source.subscribe({
+ next: v => {
+ // Should never run.
+ parentResults.push(v);
+ },
+ complete: () => {
+ // Should never run.
+ parentResults.push("complete");
+ },
+ erorr: e => {
+ // Should never run.
+ parentResults.push(e);
+ }
+ });
+ `);
+
+ assert_array_equals(results, ["subscribe", "detached"]);
+}, "No observer handlers can be invoked in detached document");
+
+promise_test(async t => {
+ const contentWin = await loadIframeAndReturnContentWindow();
+
+ // Set a global error handler on the iframe document's window, and verify that
+ // it is never called (because the thing triggering the error happens when the
+ // document is detached, and "reporting the exception" relies on an attached
+ // document).
+ contentWin.addEventListener("error",
+ t.unreached_func("Error should not be called"), { once: true });
+
+ contentWin.eval(`
+ const source = new Observable((subscriber) => {
+ // Detach the iframe and push an error, which would normally "report the
+ // exception", since this subscriber did not specify an error handler.
+ window.frameElement.remove();
+ subscriber.error("this is an error that should not be reported");
+ });
+ source.subscribe();
+ `);
+}, "Subscriber.error() does not \"report the exception\" even when an " +
+ "`error()` handler is not present, when it is invoked in a detached document");
+
+promise_test(async t => {
+ // Make this available off the global so the child can reach it.
+ window.results = [];
+ const contentWin = await loadIframeAndReturnContentWindow();
+
+ // Set a global error handler on the iframe document's window, and verify that
+ // it is never called (because the thing triggering the error happens when the
+ // document is detached, and "reporting the exception" relies on an attached
+ // document).
+ contentWin.addEventListener("error",
+ t.unreached_func("Error should not be called"), { once: true });
+
+ contentWin.eval(`
+ const parentResults = parent.results;
+ const source = new Observable((subscriber) => {
+ // This should never run.
+ parentResults.push('subscribe');
+ });
+
+ // Detach the iframe and try to subscribe.
+ window.frameElement.remove();
+ parentResults.push('detached');
+ source.subscribe();
+ `);
+
+ assert_array_equals(results, ["detached"], "Subscribe callback is never invoked");
+}, "Cannot subscribe to an Observable in a detached document");
+
+promise_test(async t => {
+ // Make this available off the global so the child can reach it.
+ window.results = [];
+ const contentWin = await loadIframeAndReturnContentWindow();
+
+ contentWin.eval(`
+ const parentResults = parent.results;
+ const event_target = new EventTarget();
+ // Set up two event listeners, both of which will mutate |parentResults|:
+ // 1. A traditional event listener
+ // 2. An observable
+ event_target.addEventListener('customevent', e => parentResults.push(e));
+ const source = event_target.on('customevent');
+ source.subscribe(e => parentResults.push(e));
+
+ // Detach the iframe and fire an event at the event target. The parent will
+ // confirm that the observable's next handler did not get invoked, because
+ // the window is detached.
+ const event = new Event('customevent');
+ window.frameElement.remove();
+ parentResults.push('detached');
+ event_target.dispatchEvent(event);
+ `);
+
+ assert_array_equals(results, ["detached"], "Subscribe callback is never invoked");
+}, "Observable from EventTarget does not get notified for events in detached documents");