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

dart2js: improve js-interop on DOM elements #39753

Open
sigmundch opened this issue Dec 11, 2019 · 3 comments
Open

dart2js: improve js-interop on DOM elements #39753

sigmundch opened this issue Dec 11, 2019 · 3 comments
Labels
area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. web-dart2js web-js-interop Issues that impact all js interop

Comments

@sigmundch
Copy link
Member

We'd like to improve the experience of using js-interop with existing types from dart:html.

Common use cases are:

  • an API in dart:html is not up to date or excludes something that is only available on a subset of browsers, so a developer wishes to use js-interop to access it
  • an API in dart:html is hidden, and users want to create their custom API to the same type.

Currently this is not supported via @JS because dart2js keeps js-interop types and other native types in separate type hierarchies.

Ideas we've discussed:

  • merge the type-hierarchies: this is not ideal because (a) is checks will degrade (any DOM type will answer true if asked is Foo where Foo is a js-interop type, (b) dynamic calls are more silent (any DOM type will accept dynamic calls on any method defined on any js-interop type).

  • no overlapping types: consider matching the @JS(name) annotation with the native names and complain if a native name from dart:html is used. This would visibly report an implicit issue we already have today. I don't believe we can do so without breaking compositionality of dart libraries in the future, though: if one library is developed using entirely js-interop and another library imports it and it separately imports dart:html, then we risk errors only coming up on that downstream dependency that combines the two libraries in one program. Today we have avoided this compositionality issue because dart:js indirectly imports dart:html.

  • match and implement types: consider matching the @JS(name) annotation with the native names and treat the js-interop type as an interface implemented by the dart:html type. If we do this, we likely want to restrict the js-interop class to be empty (so we don't add methods to the DOM class), but instead require users to use external js-interop extension methods on their Js-interop type. If we matched types, we could get code like the following to print true:

@JS('DIVElement')
class MyDiv {
}
main() {
  print(document.createElement('div') is MyDiv);
}

Open question: could js-interop types extend from one another to support patching DOM type hierarchies? This could come in tension with other ideas about sealing them in the future.

  • external js-interop extension emthods on DOM: add support for static JS-interop extension methods on both JS-interop and DOM elements.
@sigmundch sigmundch added web-dart2js web-js-interop Issues that impact all js interop area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. labels Dec 11, 2019
@donny-dont
Copy link

Hit this in #39531 in the context of trying to create a package:html completely outside of dart:html.

@jodinathan
Copy link

any news on this?

@sigmundch
Copy link
Member Author

/cc @srujzs

Thanks @jodinathan for following up.

We made some progress here, but we are not done (we are not happy with the state we are in either).

  • @srujzs added support for the no overlapping types approach described above (this is why you got an error in even without dart:html anywhere in the code it throws conflict with native dart:html type #46248). It was a first step to detect issues, which some users were running into in more surprising ways at runtime (e.g. cast errors).

  • Regarding external js-interop extension methods on DOM - we don't support yet external methods, but we do support extension methods that use js_util. This provides a pretty low-level building block, but many users have found this to be sufficient to fill the gap between the current dart:html implementation and a feature they may be missing. This is what that would look like for a hypothetical IncompleteAPI example:

import 'dart:html' show IncompleteAPI;
import 'dart:js_util' as js_util;

extension IncompleteAPIExtra on IncompleteAPI {
   int get foo => js_util.getProperty(this, 'foo'); // now IncompleteAPI has this missing property.
}

More generally, we are revamping js-interop and our updated design should avoid these issues in the future. We don't have a precise timeline on when it would land, so in the meantime, we are committed to fix or help find workarounds for blocking issues.

We'll follow up shortly on the other bug with more questions, too. Hopefully we can get a better picture of what are your requirements and how we can help unblock you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. web-dart2js web-js-interop Issues that impact all js interop
Projects
None yet
Development

No branches or pull requests

3 participants