Skip to content

Commit

Permalink
Expand dom interop to cover more uses (#2066)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
natebosch authored Jul 19, 2023
1 parent 8bc188f commit e76bffe
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 11 deletions.
1 change: 1 addition & 0 deletions pkgs/test/lib/dart.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
11 changes: 11 additions & 0 deletions pkgs/test/lib/src/runner/browser/dom.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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', <Object>[
Expand Down Expand Up @@ -135,8 +136,18 @@ extension MessageEventExtension on MessageEvent {
external String get origin;
List<MessagePort> get ports =>
js_util.getProperty<List>(this, 'ports').cast<MessagePort>();

/// 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 {}
Expand Down
9 changes: 2 additions & 7 deletions pkgs/test/lib/src/runner/browser/post_message_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<Object?> postMessageChannel() {
Expand Down Expand Up @@ -50,8 +45,8 @@ StreamChannel<Object?> 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);

Expand Down
9 changes: 5 additions & 4 deletions pkgs/test/tool/host.dart
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,11 @@ StreamChannel<dynamic> _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();

Expand Down

0 comments on commit e76bffe

Please sign in to comment.