From a58241c753c0228d19172e64db8f5c28185031c7 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 19 Jul 2023 00:01:52 +0000 Subject: [PATCH 1/2] Expand dom interop to cover more uses Add a `parent` getter on `window`. Use it to post a parent message instead of a private copy of the JS interop for the same. This had been using `@JS()` locally as a workaround for a bug in `dart:html`, and now that we aren't using `dart:html` anywhere in this code we can drop the extra copy. Expose the `source` field on `MessageEvent`. Use `js_util` to read the properties which may be missing to get to the `href` for the message. Trying to read the field through `dart:html` could throw, but after the migration to `@JS()` style interop the difference interfaces for the event source can be handled safely. Even though the host is no longer reading the href key from the messages they are still sent from the frame side for backwards compatibility with other host implementations. See #2065 --- pkgs/test/lib/dart.js | 1 + pkgs/test/lib/src/runner/browser/dom.dart | 10 ++++++++++ .../lib/src/runner/browser/post_message_channel.dart | 9 ++------- pkgs/test/tool/host.dart | 9 +++++---- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/pkgs/test/lib/dart.js b/pkgs/test/lib/dart.js index a3cc30286..4a090ef3e 100644 --- a/pkgs/test/lib/dart.js +++ b/pkgs/test/lib/dart.js @@ -12,6 +12,7 @@ window.onload = function() { // This mimics a MultiChannel-formatted message. var sendLoadException = function(message) { window.parent.postMessage({ + // TODO: https://github.com/dart-lang/test/issues/2065 - remove href "href": window.location.href, "data": [0, {"type": "loadException", "message": message}], "exception": true, diff --git a/pkgs/test/lib/src/runner/browser/dom.dart b/pkgs/test/lib/src/runner/browser/dom.dart index 48906f693..c192cbe0f 100644 --- a/pkgs/test/lib/src/runner/browser/dom.dart +++ b/pkgs/test/lib/src/runner/browser/dom.dart @@ -11,6 +11,7 @@ import 'package:js/js.dart'; class Window extends EventTarget {} extension WindowExtension on Window { + external Window get parent; external Location get location; CSSStyleDeclaration? getComputedStyle(Element elt, [String? pseudoElt]) => js_util.callMethod(this, 'getComputedStyle', [ @@ -135,8 +136,17 @@ extension MessageEventExtension on MessageEvent { external String get origin; List get ports => js_util.getProperty(this, 'ports').cast(); + /// The source may be a `WindowProxy`, a `MessagePort`, or a `ServiceWorker`. + /// + /// When a message is sent from an iframe through `window.parent.postMessage` + /// the source will be a `WindowProxy` which has the same methods as [Window]. + external MessageEventSource source; } +@JS() +@staticInterop +class MessageEventSource {} + @JS() @staticInterop class Location {} diff --git a/pkgs/test/lib/src/runner/browser/post_message_channel.dart b/pkgs/test/lib/src/runner/browser/post_message_channel.dart index e24afeb1a..55a602076 100644 --- a/pkgs/test/lib/src/runner/browser/post_message_channel.dart +++ b/pkgs/test/lib/src/runner/browser/post_message_channel.dart @@ -4,15 +4,10 @@ import 'dart:js_util'; -import 'package:js/js.dart'; import 'package:stream_channel/stream_channel.dart'; import 'dom.dart' as dom; -// Avoid using this from dart:html to work around dart-lang/sdk#32113. -@JS('window.parent.postMessage') -external void _postParentMessage(Object message, String targetOrigin); - /// Constructs a [StreamChannel] wrapping [MessageChannel] communication with /// the host page. StreamChannel postMessageChannel() { @@ -50,8 +45,8 @@ StreamChannel postMessageChannel() { // Send a ready message once we're listening so the host knows it's safe to // start sending events. - // TODO(nweiz): Stop manually adding href here once issue 22554 is fixed. - _postParentMessage( + // TODO: https://github.com/dart-lang/test/issues/2065 - remove href + dom.window.parent.postMessage( jsify({'href': dom.window.location.href, 'ready': true}) as Object, dom.window.location.origin); diff --git a/pkgs/test/tool/host.dart b/pkgs/test/tool/host.dart index 3f833b6ec..ee24a1929 100644 --- a/pkgs/test/tool/host.dart +++ b/pkgs/test/tool/host.dart @@ -209,10 +209,11 @@ StreamChannel _connectToIframe(String url, int id) { // running, but it's good practice to check the origin anyway. var message = event as dom.MessageEvent; if (message.origin != dom.window.location.origin) return; - - // TODO(nweiz): Stop manually checking href here once issue 22554 is - // fixed. - if (message.data['href'] != iframe.src) return; + // Disambiguate between frames for different test suites. + // Depending on the source type, the `location.href` may be missing. + var location = js_util.getProperty(message.source, 'location') as Object?; + if (location == null) return; + if (js_util.getProperty(location, 'href') != iframe.src) return; message.stopPropagation(); From a7cad14fd3b411c6688a10b35313957360b1eec8 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 19 Jul 2023 00:59:02 +0000 Subject: [PATCH 2/2] dart format --- pkgs/test/lib/src/runner/browser/dom.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/test/lib/src/runner/browser/dom.dart b/pkgs/test/lib/src/runner/browser/dom.dart index c192cbe0f..477158baa 100644 --- a/pkgs/test/lib/src/runner/browser/dom.dart +++ b/pkgs/test/lib/src/runner/browser/dom.dart @@ -136,6 +136,7 @@ extension MessageEventExtension on MessageEvent { external String get origin; List get ports => js_util.getProperty(this, 'ports').cast(); + /// The source may be a `WindowProxy`, a `MessagePort`, or a `ServiceWorker`. /// /// When a message is sent from an iframe through `window.parent.postMessage`