Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JS interop corrupt DOM element if is used as argument in dart 1.14 and above (cross frame access issue) #25871

Closed
mouze opened this issue Feb 26, 2016 · 7 comments
Assignees
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. closed-obsolete Closed as the reported issue is no longer relevant library-html web-js-interop Issues that impact all js interop

Comments

@mouze
Copy link

mouze commented Feb 26, 2016

For our application we need to work with DOM elements inside iFrame.
Because DART does not allow cross-frame access even if window use same origin I must make little hack:

In DART:

//define JS function:
@JS("replaceElementInIframe")
external bool _replaceElementInIframe(frameSelector, elementSelector, newelement);

//make element:
var div = new html.DivElement();
// call JS
_replaceElementInIframe(iFrameSelector, innerDivSelector, div);

In JS function do something like this:

window.replaceElementInIframe = function (frameSelector, elementSelector, newelement){
        // select iframe
    var frame = document.querySelector(frameSelector)

        // select document
        var doc = (frame.contentWindow ? frame.contentWindow.document : frame.contentDocument);

        // select element inside iframe
    var foundedElement = doc.querySelector(elementSelector);

        // replace element inside iframe by element given as argument from DART
    foundedElement.parentNode.replaceChild(newelement, foundedElement);
    return true;
 }

In DART 1.13 and before
After I call _replaceElementInIframe I can take from div his ownerDocument without error and work with it as I want. For example insert other nodes to it, listen events ...

In DART 1.14 and above (1.15.0-dev.4.0 (ref 43e12db))
When I try to read ownerDocument from div, DART throws exception:
type 'JsObjectImpl' is not a subtype of type 'Document' of 'function result'.
(Same error is thrown if I try to read div.parentNode)

I try to use package:js and dart:js with same result. (with dart:js is little different code)

This is very limiting for us, because we cannot upgrade from DART 1.13 where are some other bugs which may be repaired in 1.14

@anders-sandholm anders-sandholm added area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-html labels Feb 29, 2016
@anders-sandholm
Copy link
Contributor

Not sure if this is an HTML lib issue at the root - or if this is something that needs fixing in our JS interop story. Please re-label accordingly.

@alan-knight alan-knight added the web-js-interop Issues that impact all js interop label Mar 1, 2016
@alan-knight
Copy link
Contributor

Is this in Dartium or dart2js?

Cross-frame access is difficult, because the objects have different prototypes. I'll guess this is Dartium, and what's happening is that the conversion is not recognizing the other frame's document as needing to be converted to Document. But @jacob314 is the expert.

@mouze
Copy link
Author

mouze commented Mar 1, 2016

This problem is only in Dartium.

If I look deeper:
When I try to read ownerDocument property on div I goto file "html_dartium.dart" on line with command
Document get ownerDocument => wrap_jso(blink.BlinkNode.instance.ownerDocument_Getter(unwrap_jso(this)));

part
blink.BlinkNode.instance.ownerDocument_Getter(unwrap_jso(this))
works same in both versions.

but problem may be in function wrap_jso
in 1.13 it returns - Instance of 'HtmlDocument'
in 1.14 it returns - [object HTMLDocument]

And I mean it depend on modification in file
\dart-sdk\lib\html\html_common\conversions_dartium.dart
on line 124 there is condition
1.13 - if (wrapper != null && wrapper is! js.JsObject) {
1.14 - if (wrapper != null) {

1.14 - condition is true and function return bad value wrapper::class is JsObjectImpl
1.13 - condition is false and program continue to next lines and function ends on line 206 command "return dartClass_instance;" where "dartClass_instance" is Instance of 'HtmlDocument'

@jacob314 jacob314 self-assigned this Jul 7, 2016
@jacob314 jacob314 changed the title JS interop corrupt DOM element if is used as argument in dart 1.14 and above JS interop corrupt DOM element if is used as argument in dart 1.14 and above (cross frame access issue) Jul 8, 2016
@jacob314 jacob314 mentioned this issue Jul 8, 2016
19 tasks
@jacob314
Copy link
Member

Some good news and some bad news.

Bad news: the fact that this worked in Dartium 1.13 is a bug not a feature. The design was you should not be able to get access DOM objects from a different frame. You found a clever way to work around the restrictions we had in place to stop cross frame access by from JS switching what document an element was part of.
Good news: we will provide better cross-frame access going forward. Now that memory leak free dartium is not a priority we can do a lot better. The current strawman design is to provide an
enableDart(IFrameElement e) method that you could call to enable Dart support on an iframe. If you call this method then from that point forward all objects in the iframe can be accessed the same as you would if they were in our main window. Let me know if this approach would work for you. There would be some small cost to calling enableDart on an iframe so it would work well if you have a moderate number of iframes (e.g. 5) not if you have 200 iframes.

@mouze
Copy link
Author

mouze commented Aug 2, 2016

Sounds good for us.
Will be there some "disableDart(IFrameElement e)"?
Because we build single page application and in session live time we create and destroy iFrame objects. We have only one or two iFrames at the same time in DOM.

Thank you for your response.

@jacob314
Copy link
Member

There isn't a need for disableDart method. Creating and destroying iframe objects that have enableDart called on them will not leak memory. Think of it like enabling a JS polyfill on the iframe.

@matanlurey matanlurey added the closed-obsolete Closed as the reported issue is no longer relevant label Jun 19, 2018
@matanlurey
Copy link
Contributor

Please re-open if this is still the case with the latest 2.0.0-dev SDK.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. closed-obsolete Closed as the reported issue is no longer relevant library-html web-js-interop Issues that impact all js interop
Projects
None yet
Development

No branches or pull requests

5 participants