dart-lang / sdk

The Dart SDK, including the VM, dart2js, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
9.95k stars 1.53k forks source link

In dart2js html.window.opener is not null even when window was not opened by being linked to or created by another window #37621

Open todbachman-wf opened 4 years ago

todbachman-wf commented 4 years ago

In code compiled using dart2js, our experience is that html.window.opener is never null even if the window wasn't spawned from another window. According to the MDN docs, it should be. In DDC it is null as expected.

We currently rely on a null check on html.window.opener before calling methods on it. That now doesn't suffice because some of these methods, like postMessage, end up throwing exceptions when opener ought to have been null. So we're having to do additional exception handling around those calls because a null check doesn't work in dart2js.

My Environment:

vsmenon commented 4 years ago

Hmm, do you know if it is actually non-null at runtime (e.g., does it print as non-null)? It's possible that dart2js thinks it's non-null and incorrectly optimizing away the check.

todbachman-wf commented 4 years ago

The behavior we are seeing is html.window.opener is non-null at runtime. Its type is _DomWindowCrossFrame. Since it is not null, we've been trying to call postMessage on it. Something inside postMessage ends up throwing "NoSuchMethodError: method not found: 'postMessage' on null".

rakudrama commented 4 years ago

It looks like these parts of sdk/lib/html/dart2js/html_dart2js.dart might be to blame:

  WindowBase get opener => _convertNativeToDart_Window(this._get_opener);
  @JSName('opener')
  @Creates('Window|=Object')
  @Returns('Window|=Object')
  final dynamic _get_opener;

...
WindowBase _convertNativeToDart_Window(win) {
  if (win == null) return null;
  return _DOMWindowCrossFrame._createSafe(win);
}

Try changing @Returns('Window|=Object') to @Returns('Window|=Object|Null')

document.window has the |Null, so it might be sufficient to use document.window somewhere.

todbachman-wf commented 4 years ago

@rakudrama I gave the change you suggested a try and it does indeed return null when expected and is non-null when one would expect.

tbelousova commented 4 years ago

We here have the same issue with iframe.contentWindow. When iframe is not initialized contentWindow should be null. That's how we test it before calling postMessage. But iframe.contentWindow is never null in built version. We did non-minified build and see that actual implementation of _convertNativeToDart_Window differs from one in sdk/lib/html/dart2js/html_dart2js.dart.

Here is what we have in build:

_convertNativeToDart_Window: function(win) { return W._DOMWindowCrossFrame__createSafe(win); }

Dart SDK Version: 2.5.0, 2.5.1 MacOSX Chrome