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

[2.19] Add next-generation preview section to js-interop page #4528

Merged
merged 13 commits into from
Jan 27, 2023
107 changes: 107 additions & 0 deletions src/web/js-interop.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,110 @@ For help using the `js` package, see the following:
[js-api]: {{site.pub-api}}/js
[sass]: {{site.pub-pkg}}/sass

## Next-generation JS interop preview

{{site.alert.note}}
This interop feature is **experimental**,
and [in active development](https://github.com/dart-lang/sdk/issues/35084).
{{site.alert.end}}

Dart's JS interop story is currently evolving.
Many of the features that enable future JS interop
are ready to experiment with as of Dart version 2.19.
These features support the existing production
and development web compilers, as well as Dart's
in-progress Wasm compiler ([`dart2wasm`][]).

For a glimpse into the next generation of JS interop,
you can refactor your code to conform to the new
syntax and semantics now. Doing so will
likely not prevent the need to refactor again once
[Dart 3][] lands, as the features are still in development.
However, the features available for preview are much
closer to future JS interop than any pattern supported today.
So, there are a few reasons to try them out now:

* New JS interop developers can learn and build with future JS interop
so they won't have to unlearn obsolete patterns in a few months.
* Existing JS interop developers eager to experiment with
the latest features in JS interop
or with `dart2wasm` when it becomes available.
* Potentially ease transition of existing JS
interop code once migration becomes necessary.

The following sections are the set of features
expected to work across compilers for JS interop.

*Requirements:*
* Dart SDK constraint: `>= 2.19`
* [`package:js`][] constraint: `>= 0.6.6`

[`dart2wasm`]: https://github.com/dart-lang/sdk/blob/main/pkg/dart2wasm/dart2wasm.md#running-dart2wasm
[Dart 3]: https://medium.com/dartlang/the-road-to-dart-3-afdd580fbefa
[`package:js`]: {{site.pub-pkg}}/js

### `package:js`

The key feature of next-generation JS interop is [static interop][].
We recommend using static interop as the default for `package:js`,
as it is more declaritive, more likely to be optimized,
MaryaBelanger marked this conversation as resolved.
Show resolved Hide resolved
more likely to perform better, and required for `dart2wasm`.
Static interop addresses several gaps in the existing JS interop story:

* **Missing features:** Static interop enables previously
unavailable features, like easily wrapping and transforming APIs,
renaming members, and static checking.

* **Inconsistencies:** Static interop makes backends more consistent,
so development and production web compilers won't behave as differently
as before.

* **Clarity:** Static interop takes a step towards making JS interop
more idiomatic in Dart, and making the boundary between the two languages more visible.
For example, it enforces that JS classes are not meant to be mixed with Dart
(e.g. no dynamic calls, JS interop types cannot be implemented as a Dart class).
MaryaBelanger marked this conversation as resolved.
Show resolved Hide resolved
We expect upcoming integration with inline classes
will help make interop even more idiomatic.

You can implement static interop using the `package:js`
annotation `@staticInterop`.
The set of features for future static interop currently includes:
* `@staticInterop` interfaces
* External factory constructors with and without `@anonymous`
* External `static` class members
* External non-`static` extension members on a `@staticInterop`
class (fields, getters, setters, methods)
* Non-external extension members on a `@staticInterop` class
* Top-level external members
* [`@JSExport`][] for mocking and exports

To learn how to implement static interop and see examples,
visit the [static interop][] specification.

[static interop]: https://pub.dev/packages/js#staticinterop
MaryaBelanger marked this conversation as resolved.
Show resolved Hide resolved
[`@JSExport`]: https://pub.dev/packages/js#jsexport-and-js_utilcreatedartexport
MaryaBelanger marked this conversation as resolved.
Show resolved Hide resolved


### `dart:js_util`
MaryaBelanger marked this conversation as resolved.
Show resolved Hide resolved

We recommend using static interop over `js_util`
in future JS interop.
MaryaBelanger marked this conversation as resolved.
Show resolved Hide resolved

However, since [`js_util`][] provides lower-level
MaryaBelanger marked this conversation as resolved.
Show resolved Hide resolved
functionality than static interop, it can be
configured in a more granular, customizable way.
This means `js_util` could *potentially* help with
some rare edge cases we haven't accounted for yet,
that static interop won't be able to address.

For example, we may discover that some migrations are
parlough marked this conversation as resolved.
Show resolved Hide resolved
easier to accomplish with `js_util`. Preexisting uses of
`dart:js` (now deprecated) can be replaced by a combination
of static interop and `dart:js_util`.
The former is what we recommend, but it may be easier
to automate migrations using the latter.

While `dart:js_util` is supported by `dart2wasm` in future interop,
MaryaBelanger marked this conversation as resolved.
Show resolved Hide resolved
it won't be as ergonomic, and won't be optimized.

[`js_util`]: {{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-js_util/dart-js_util-library.html