We'd like to significantly improve Dart's ability to interoperate with JavaScript libraries and vice versa. This will build on existing capabilities (see examples of current JS interop).
The new design will take advantage of Dart 2's sound static typing to provide JS interop that is convenient, high performance, and with minimal code size impact.
Some of the tasks for this:
Some of the things we'll need to address (details are subject to change):
JSMap type)dynamic (e.g. JSDynamic that dispatches directly to JS members)Other details:
this binding for tearoffs (#32370)Dynamic dispatch support:
We will likely want to keep opt-in dynamic dispatch support, similar to what "dart:html" currently provides, but well specified and available for use by any JS interop class. The classes must opt-in for this. This will cause extra data to be retained for use by runtime dispatch. Type checks are not required, however. The types will use the relaxed JS interop casting rules. Calling conventions in dart:html can likely be simplified (e.g. we do not require obj.foo(x) and obj.foo(x, null) to substitute undefined for null). Similar to JS Array and JS function types, tearoffs of JS methods will be untyped and not checked (they can be converted to any function type).
Because of these changes, we should be able to reduce the signature data stored for dart:html. These changes should be largely non-breaking, as code rarely relies on dart:html throwing type errors (indeed, such code will rarely work in production mode, which omits checks). It is also unlikely that any code is relying on dynamic tearoffs having a specific reified function type.
Note that any data for automatic conversions, or extension methods added to the types, will need to be stored so runtime dispatch can access it. Currently it is implementation defined how these methods are stored (dart2js uses interceptors , dartdevc adds symbolized members to the JS classes). If we want these methods to be accessible from JS (e.g. they are exported), we'll need to specify this precisely. A similar issue exists for the static extension methods (described above).
Longer term: we'd like to use the new JS interop to implement the DOM in a package, and then migrate from "dart:html". This will necessarily be a slow migration/deprecation process, since "dart:html" is necessary for all web apps today. It may involve automated refactoring tools or opt-in static analysis to assist the migration.
Due to these changes, migration to the new dart:html package should not be difficult (likely as simple as importing "package:html/html1.dart"). We will want a static-only version of dart:html, however (e.g. "package:html/html2.dart"). Types from those two HTML libraries should be compatible, so one can cast between them (after all, it is the same JS object underneath). At compile time, an explicit cast may be required (we could allow old types to be converted to new types, though, and you could always go in the other direction with as html1.Element because runtime casting will be allowed).
Ideally, we use re-export to declare the "dynamic version" of package:html:
// in file html1.dart
import "package:js/js.dart" as js;
@js.SupportsDynamicDispatch()
export "html2.dart";
That library simply indicates that dynamic dispatch data should be generated. If "html1.dart" is not imported, the runtime dispatch data would not be generated.
I've added a section about opt-in support for dynamic dispatch. Mainly this is intended to ease dart:html migration. But it's also a capability that we support in both dart4web compilers, so I believe we can offer it for broader use. It makes the interop a bit friendlier to use, at the cost of some extra runtime data. (probably not as much as dart:html currently retains, due to the elimination of checks for JS interop types)
Cool, thanks for adding that!
Very early draft (apologies, it may have lots of typos/bugs) is here: https://github.com/dart-lang/sdk/blob/js_interop/pkg/js/proposal.md ... I'm out of town for a week, but I'd like to do an edit pass when I get back.
@jmesserly 鈥撀燿o you plan to merge that branch in? After feedback? Just curious...
do you plan to merge that branch in? After feedback? Just curious...
yes, there's a CL up for it, will send out after a bit more time to gather feedback
@jmesserly any updates on this?
This proposal looks amazing .. any update here?
We do plan on working towards parts of the proposal, but not all at once.
In the near term the focus is on removing some of the differences between dart2js and DDC behavior so there are less surprises when moving from development to production. Currently working toward making allowInterop as required as feasible in DDC (we can't change calling semantics completely so can't get 100% safety) so it's harder to accidentally omit it, and to make the wrapped callbacks strict about arguments in DDC to match dart2js.
We also have plans to move the discussion forward around the JsAny type checking.
We won't be making any changes around static extension methods that are specific to JS interop, since we expect that the real language feature will fill that gap. We also are unsure about the future plans around dart:html or a Dart team owned package:html that might replace it.
Could we support Web Components blocked by https://github.com/dart-lang/sdk/issues/35829?
Related SO: https://stackoverflow.com/questions/25295022/dart-custom-elements-vanilla-dart-without-polymer/63684036
Web Components: https://www.polymer-project.org/blog/2020-01-15-edge-79-releaseWeb Components since v5.3: https://medium.com/storybookjs/storybook-5-3-83e114e8797cWeb Components helps to cross-platform build Design System for Dart web-simple, AngularDart and even Flutter Web (by using HtmlElementView)
Most helpful comment
@jmesserly any updates on this?