Skip to content

Commit

Permalink
Add docs for ExternalDartReference (dart-lang#5668)
Browse files Browse the repository at this point in the history
This type was added as part of
dart-lang/sdk#55187 to dart:js_interop for a
faster alternative to JSBoxedDartObject, so we should add some
documentation on it.
  • Loading branch information
srujzs authored Apr 2, 2024
1 parent cc7d172 commit a7e58cc
Showing 1 changed file with 35 additions and 8 deletions.
43 changes: 35 additions & 8 deletions src/content/interop/js-interop/js-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ JS types form a natural type hierarchy:
- JS typed arrays like `JSUint8Array`
- `JSBoxedDartObject`, which allows users to box and pass Dart values
opaquely within the same Dart runtime
- From Dart 3.4 onwards, the type `ExternalDartReference` in
`dart:js_interop` also allows users to pass Dart values opaquely, but is
*not* a JS type. Learn more about the tradeoffs between each option
[here](#jsboxeddartobject-vs-externaldartreference).

You can find the definition of each type in the [`dart:js_interop` API docs].

Expand Down Expand Up @@ -72,14 +76,15 @@ Generally, the conversion table looks like the following:

<div class="table-wrapper" markdown="1">

| JS type | Dart type |
|-------------------------------------|------------------------------------------|
| `dart:js_interop` type | Dart type |
| ----------------------------------- | ---------------------------------------- |
| `JSNumber`, `JSBoolean`, `JSString` | `num`, `int`, `double`, `bool`, `String` |
| `JSExportedDartFunction` | `Function` |
| `JSArray<T extends JSAny?>` | `List<T extends JSAny?>` |
| `JSPromise<T extends JSAny?>` | `Future<T extends JSAny?>` |
| Typed arrays like `JSUint8Array` | Typed lists from `dart:typed_data` |
| `JSBoxedDartObject` | Opaque Dart value |
| `ExternalDartReference` | Opaque Dart value |

{:.table .table-striped}
</div>
Expand All @@ -103,8 +108,8 @@ specific conversion function for more details.
In order to ensure type safety and consistency, the compiler places requirements
on what types can flow into and out of JS. Passing arbitrary Dart values into JS
is not allowed. Instead, the compiler requires users to use a compatible interop
type or a primitive, which would then be implicitly converted by the compiler.
For example, these would be allowed:
type, `ExternalDartReference`, or a primitive, which would then be implicitly
converted by the compiler. For example, these would be allowed:

```dart tag=good
@JS()
Expand All @@ -123,6 +128,11 @@ extension type InteropType(JSObject _) implements JSObject {}
external InteropType get interopType;
```

```dart tag=good
@JS()
external void externalDartReference(ExternalDartReference _);
```

Whereas these would return an error:

```dart tag=bad
Expand Down Expand Up @@ -240,9 +250,22 @@ to interop members or distinguish between JS `null` and `undefined` values,
but this will likely change in the future. See [#54025] for more details.
:::

{% comment %}
TODO: add links (with stable) when ready:
{% endcomment %}
## `JSBoxedDartObject` vs `ExternalDartReference`

From Dart 3.4 onwards, both [`JSBoxedDartObject`] and [`ExternalDartReference`]
can be used to pass opaque references to Dart `Object`s through JavaScript.
However, `JSBoxedDartObject` wraps the opaque reference in a JavaScript object,
while `ExternalDartReference` is the reference itself and therefore is not a JS
type.

Use `JSBoxedDartObject` if you need a JS type or if you need extra checks to
make sure Dart values don't get passed to another Dart runtime. For example, if
the Dart object needs to be placed in a `JSArray` or passed to an API that
accepts a `JSAny`, use `JSBoxedDartObject`. Use `ExternalDartReference`
otherwise as it will be faster.

See [`toExternalReference`] and [`toDartObject`] to convert to and from an
`ExternalDartReference`.

[`dart:js_interop`]: {{site.dart-api}}/{{site.sdkInfo.channel}}/dart-js_interop/dart-js_interop-library.html
[`external`]: /language/functions#external
Expand All @@ -252,4 +275,8 @@ TODO: add links (with stable) when ready:
[`instanceOfString`]: {{site.dart-api}}/{{site.sdkInfo.channel}}/dart-js_interop/JSAnyUtilityExtension/instanceOfString.html
[`isA`]: {{site.dart-api}}/{{site.sdkInfo.channel}}/dart-js_interop/JSAnyUtilityExtension/isA.html
[#4841]: https://github.com/dart-lang/linter/issues/4841
[#54025]: https://github.com/dart-lang/sdk/issues/54025
[#54025]: https://github.com/dart-lang/sdk/issues/54025
[`JSBoxedDartObject`]: {{site.dart-api}}/{{site.sdkInfo.channel}}/dart-js_interop/JSBoxedDartObject-extension-type.html
[`ExternalDartReference`]: {{site.dart-api}}/{{site.sdkInfo.channel}}/dart-js_interop/ExternalDartReference-extension-type.html
[`toExternalReference`]: {{site.dart-api}}/{{site.sdkInfo.channel}}/dart-js_interop/ObjectToExternalDartReference/toExternalReference.html
[`toDartObject`]: {{site.dart-api}}/{{site.sdkInfo.channel}}/dart-js_interop/ExternalDartReferenceToObject/toDartObject.html

0 comments on commit a7e58cc

Please sign in to comment.