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.