Skip to content

Commit e04e2d1

Browse files
committed
Update past JS interop section
Reorganizes the section to be chronological and notes differences and similarities between old interop and current interop. Also mentions that these are legacy and unsupported for Wasm.
1 parent 8c2b89f commit e04e2d1

File tree

1 file changed

+109
-48
lines changed

1 file changed

+109
-48
lines changed
+109-48
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,120 @@
11
---
22
title: Past JS interop
3-
description: Archive of past JS interop implementations
3+
description: Archive of past JS interop implementations.
44
---
55

6-
This page addresses previous iterations of JS interop for Dart:
7-
* `package:js`
8-
* `dart:js`
6+
This page addresses previous iterations of JS interop for Dart that are
7+
considered legacy. They are not necessarily deprecated, but might be in the
8+
future. Therefore, prefer using [`dart:js_interop`] going forwards and migrate
9+
usages of old interop libraries when possible. While [`dart:html`] and other web
10+
libraries are closely related, they're covered in the [`package:web`] page.
911

10-
**We do not recommend using any JS interop solution other than [static interop][].**
11-
12-
Each of these tools still exist and are usable.
13-
However, the static interop model
14-
is more performant, provides more capabilities,
15-
and will continue to be supported and developed.
16-
If you are just starting out with JS interop in Dart,
17-
please start with the static interop library, [`js_interop`][].
18-
19-
[static interop]: /interop/js-interop
20-
[`js_interop`]: {{site.dart-api}}/js_interop
21-
22-
## `package:js`
23-
24-
// *This section probably doesn't make any sense*
25-
26-
[**`package:js` API docs**]
27-
28-
**We will not continue to support `package:js` alongside static interop.**
29-
30-
The `package:js` library can represent objects in different ways with its
31-
class type annotations:
32-
33-
* [`@JS`]
34-
* [`@anonymous`]
35-
* [`@staticInterop`]
36-
37-
Because `package:js` supports dynamic invocations of external members (the
38-
opposite of static interop), its static type checking capabilities are
39-
much more limited than static interop, and therefore cannot be fully sound.
40-
For the same reason, `package:js` can not interop with [DOM APIs][].
41-
42-
[**`package:js` API docs**]: {{site.pub-pkg}}/js
43-
[`@JS`]: /interop/js-interop/reference#js
44-
[`@Anonymous`]: /interop/js-interop/reference
45-
[`@staticInterop`]: /interop/js-interop/reference
46-
[DOM APIs]: /interop/js-interop/dom
12+
{{site.alert.warn}}
13+
None of these legacy interop libraries are supported when compiling to Wasm.
14+
{{site.alert.end}}
4715

4816
## `dart:js`
4917

50-
[**`dart:js` API docs**]
18+
[`dart:js`] exposed a concrete [`class wrapper`] to interop with JS objects.
19+
This wrapper contained methods to dynamically get, set, and call properties on
20+
the wrapped JS object. It was less performant to use due to the use of a class
21+
wrapper and ergonomically more difficult to use as you couldn't declare interop
22+
members. Many of the functionalities exposed in `dart:js` like [`allowInterop`]
23+
were later re-exposed through other interop libraries.
5124

52-
**We will not continue to support `dart:js` alongside static interop.**
25+
This library has been legacy ever since `package:js` and `dart:js_util` were
26+
released. It is likely the first to be deprecated.
5327

54-
The `dart:js` library is a low-level API for non-static interop with JavaScript.
55-
It's wrapper-based model requires much more overhead,
56-
and is much more expensive and slow,
57-
than static interop's zero-cost wrapper model.
28+
## `package:js`
5829

59-
[**`dart:js` API docs**]: {{site.dart-api}}/dart-js/dart-js-library.html
30+
[`package:js`] introduced functionality to declare interop types and members.
31+
It allowed users to write interop classes instead of interop extension types. At
32+
runtime, these classes were erased to a type that is similar to
33+
`dart:js_interop`'s [`JSObject`].
34+
35+
```dart
36+
@JS()
37+
class JSType {}
38+
```
39+
40+
Users who have used this package will find the syntax and semantics of
41+
`dart:js_interop` familiar. You may be able to migrate to `dart:js_interop` by
42+
replacing the class definition with an extension type and have it work in many
43+
cases.
44+
45+
There are significant differences, however:
46+
47+
- `package:js` types could not be used to interop with browser APIs.
48+
- `package:js` allowed dynamic dispatch. This meant that if you casted the
49+
`package:js` type to `dynamic` and called an interop member on it, it would
50+
forward to the right member. This is no longer possible with
51+
`dart:js_interop`.
52+
- `package:js`' [`@JS`] has different soundness guarantees. `external` members
53+
would not have their return types checked. This is also why there's a
54+
[separate `@JS`] annotation in `dart:js_interop` that users should use
55+
instead.
56+
- `package:js` types could not rename instance members or have non-`external`
57+
members.
58+
- `package:js` types could subtype and be a supertype of non-interop classes.
59+
This was often used for mocks.
60+
- [`@anonymous`] types were a way to declare an interop type with an object
61+
literal constructor. `dart:js_interop` does not use this annotation and treats
62+
all `external` named-argument constructors as object literal constructors.
63+
64+
### `@staticInterop`
65+
66+
Along with `@JS` and `@anonymous`, `package:js` later exposed
67+
[`@staticInterop`], which was a prototype of interop extension types.
68+
69+
`@staticInterop` types were implicitly erased to `JSObject`. It required users
70+
to declare all instance members in extensions so that only static semantics
71+
could be used, and had stronger soundness guarantees. Users could use it to
72+
interact with browser APIs, and it also allowed things like renaming and
73+
non-`external` members. Like interop extension types, it didn't have support for
74+
dynamic dispatch.
75+
76+
`@staticInterop` classes can almost always be migrated to an interop extension
77+
type by just changing the class to an extension type and removing the
78+
annotations.
79+
80+
`dart:js_interop` exposed `@staticInterop` (and `@anonymous`, but only if
81+
`@staticInterop` is also used) to support static interop semantics until
82+
extension types were added to the language. All such types should now be
83+
migrated to extension types.
84+
85+
## `dart:js_util`
86+
87+
[`dart:js_util`] supplied a number of utility functions that could not be
88+
declared in an interop type or were necessary for values to be passed back and
89+
forth. This included members like:
90+
91+
- `allowInterop` (which is now [`Function.toJS`])
92+
- `getProperty`/`setProperty`/`callMethod`/`callConstructor` (which are now in
93+
[`dart:js_interop_unsafe`])
94+
- Various JS operators
95+
- Type-checking helpers
96+
- Mocking support
97+
98+
and more. `dart:js_interop` and `dart:js_interop_unsafe` contain these helpers
99+
now with possibly alternate syntax.
100+
101+
{% comment %}
102+
TODO: add links (with stable) when ready:
103+
TODO: Link to `package:web` section
104+
{% endcomment %}
105+
106+
[`dart:js_interop`]: https://api.dart.dev/dev/dart-js_interop
107+
[`dart:html`]: https://api.dart.dev/dev/dart-html
108+
[`package:web`]: /
109+
[`dart:js`]: https://api.dart.dev/dev/dart-js
110+
[`class wrapper`]: https://api.dart.dev/dev/dart-js/JsObject-class.html
111+
[`allowInterop`]: https://api.dart.dev/dev/dart-js_util/allowInterop.html
112+
[`package:js`]: https://pub.dev/packages/js
113+
[`JSObject`]: https://api.dart.dev/dev/dart-js_interop/JSObject-extension-type.html
114+
[`@JS`]: https://github.com/dart-lang/sdk/blob/main/sdk/lib/js/_js_annotations.dart#L11
115+
[separate `@JS`]: https://api.dart.dev/dev/dart-js_interop/JS-class.html
116+
[`@anonymous`]: https://github.com/dart-lang/sdk/blob/main/sdk/lib/js/_js_annotations.dart#L40
117+
[`@staticInterop`]: https://github.com/dart-lang/sdk/blob/main/sdk/lib/js/_js_annotations.dart#L48
118+
[`dart:js_util`]: https://api.dart.dev/dev/dart-js_util
119+
[`Function.toJS`]: https://api.dart.dev/dev/dart-js_interop/FunctionToJSExportedDartFunction/toJS.html
120+
[`dart:js_interop_unsafe`]: https://api.dart.dev/dev/dart-js_interop_unsafe

0 commit comments

Comments
 (0)