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

Add docs for ExternalDartReference #5668

Merged
merged 5 commits into from
Apr 2, 2024
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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].

MaryaBelanger marked this conversation as resolved.
Show resolved Hide resolved
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 |
|-------------------------------------|------------------------------------------|
| 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`]: https://api.dart.dev/main/dart-js_interop/JSBoxedDartObject-extension-type.html
[`ExternalDartReference`]: https://api.dart.dev/main/dart-js_interop/ExternalDartReference-extension-type.html
[`toExternalReference`]: https://api.dart.dev/main/dart-js_interop/ObjectToExternalDartReference/toExternalReference.html
[`toDartObject`]: https://api.dart.dev/main/dart-js_interop/ExternalDartReferenceToObject/toDartObject.html
srujzs marked this conversation as resolved.
Show resolved Hide resolved