Add tests for cross-origin window and location
Tests that we can use JSAny? as the type without
violating cross-origin policy. This will then be
used in package:web to implement a wrapper.
Change-Id: Ic30557138b61e27e421747ead81ea2fb7f6db240
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/381886
Commit-Queue: Srujan Gaddam <srujzs@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/tests/lib/js/static_interop_test/cross_origin_test.dart b/tests/lib/js/static_interop_test/cross_origin_test.dart
new file mode 100644
index 0000000..939e7b5
--- /dev/null
+++ b/tests/lib/js/static_interop_test/cross_origin_test.dart
@@ -0,0 +1,105 @@
+// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that `JSAny?` can be used in some guaranteed ways to interact with
+// cross-origin objects.
+
+import 'dart:js_interop';
+
+import 'package:expect/expect.dart';
+
+@JS('Object.is')
+external bool _is(CrossOriginWindow a, CrossOriginWindow b);
+
+@JS()
+external Window get window;
+
+@JS('document.body.append')
+external void append(HTMLIFrameElement iframe);
+
+@JS('document.createElement')
+external JSObject _createElement(String tag);
+
+HTMLIFrameElement createIFrame() => HTMLIFrameElement(_createElement('iframe'));
+
+// Should be aligned with the members used in `cross_origin.dart` from
+// `package:web`.
+extension type CrossOriginWindow(JSAny? _) {
+ external bool get closed;
+ external int get length;
+ external CrossOriginLocation get location;
+ external set locationString(String value);
+ external CrossOriginWindow get opener;
+ external CrossOriginWindow get parent;
+ external CrossOriginWindow get top;
+ external CrossOriginWindow get frames;
+ external CrossOriginWindow get self;
+ external CrossOriginWindow get window;
+ external void blur();
+ external void close();
+ external void focus();
+ external void postMessage(
+ JSAny? message, [
+ JSAny optionsOrTargetOrigin,
+ JSArray<JSObject> transfer,
+ ]);
+}
+
+extension type Window(CrossOriginWindow _) implements CrossOriginWindow {
+ external CrossOriginWindow open(String url);
+}
+
+// Should be aligned with the members used in `cross_origin.dart` from
+// `package:web`.
+extension type CrossOriginLocation(JSAny? _) {
+ external void replace(String url);
+ external set href(String value);
+}
+
+extension type HTMLIFrameElement(JSObject _) implements JSObject {
+ external CrossOriginWindow get contentWindow;
+ external set src(String value);
+}
+
+void main() {
+ const url = 'https://www.google.com';
+ const url2 = 'https://www.example.org';
+
+ void testCommon(CrossOriginWindow crossOriginWindow) {
+ Expect.equals(crossOriginWindow.length, 0);
+ Expect.isFalse(crossOriginWindow.closed);
+ crossOriginWindow.location.replace(url2);
+ crossOriginWindow.location.href = url;
+ crossOriginWindow.locationString = url2;
+ crossOriginWindow.postMessage('hello world'.toJS);
+ crossOriginWindow.postMessage('hello world'.toJS, url2.toJS);
+ crossOriginWindow.postMessage('hello world'.toJS, url2.toJS, JSArray());
+ crossOriginWindow.blur();
+ crossOriginWindow.focus();
+ crossOriginWindow.close();
+ }
+
+ final openedWindow = window.open(url);
+ Expect.isTrue(_is(openedWindow.opener, window));
+ Expect.isTrue(_is(openedWindow.parent, openedWindow));
+ Expect.isTrue(_is(openedWindow.top, openedWindow));
+ Expect.isTrue(_is(openedWindow.frames, openedWindow));
+ Expect.isTrue(_is(openedWindow.self, openedWindow));
+ Expect.isTrue(_is(openedWindow.window, openedWindow));
+ testCommon(openedWindow);
+ Expect.isTrue(openedWindow.closed);
+
+ final iframe = createIFrame();
+ iframe.src = url;
+ append(iframe);
+ final contentWindow = iframe.contentWindow;
+ Expect.isTrue(_is(contentWindow.opener, CrossOriginWindow(null)));
+ Expect.isTrue(_is(contentWindow.parent, window));
+ Expect.isTrue(_is(contentWindow.top, window.top));
+ Expect.isTrue(_is(contentWindow.frames, contentWindow));
+ Expect.isTrue(_is(contentWindow.self, contentWindow));
+ Expect.isTrue(_is(contentWindow.window, contentWindow));
+ testCommon(contentWindow);
+ Expect.isFalse(contentWindow.closed);
+}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 7b35f9f..f2c8774 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -96,6 +96,7 @@
[ $jscl ]
js/export/static_interop_mock/proto_test: SkipByDesign # Uses dart:html.
js/static_interop_test/constants_test: SkipByDesign # Uses dart:html.
+js/static_interop_test/cross_origin_test: SkipByDesign # Uses the DOM.
js/static_interop_test/futurevaluetype_test: SkipByDesign # Uses dart:html.
js/static_interop_test/import/import_test: SkipByDesign # TODO(srujzs): This test uses the file system to load a module. Since the test runner doesn't start an HTTP server for commandline JS shells, I don't think this is supported.
js/static_interop_test/supertype_transform_test: SkipByDesign # Uses dart:html.