From a7e58cc9db998841703181976afa1f2b5af00315 Mon Sep 17 00:00:00 2001
From: Srujan Gaddam <58529443+srujzs@users.noreply.github.com>
Date: Tue, 2 Apr 2024 08:58:01 -0700
Subject: [PATCH] Add docs for ExternalDartReference (#5668)
This type was added as part of
https://github.com/dart-lang/sdk/issues/55187 to dart:js_interop for a
faster alternative to JSBoxedDartObject, so we should add some
documentation on it.
---
src/content/interop/js-interop/js-types.md | 43 ++++++++++++++++++----
1 file changed, 35 insertions(+), 8 deletions(-)
diff --git a/src/content/interop/js-interop/js-types.md b/src/content/interop/js-interop/js-types.md
index 94cf890b29..c7e96f0388 100644
--- a/src/content/interop/js-interop/js-types.md
+++ b/src/content/interop/js-interop/js-types.md
@@ -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].
@@ -72,14 +76,15 @@ Generally, the conversion table looks like the following:
-| JS type | Dart type |
-|-------------------------------------|------------------------------------------|
+| `dart:js_interop` type | Dart type |
+| ----------------------------------- | ---------------------------------------- |
| `JSNumber`, `JSBoolean`, `JSString` | `num`, `int`, `double`, `bool`, `String` |
| `JSExportedDartFunction` | `Function` |
| `JSArray` | `List` |
| `JSPromise` | `Future` |
| Typed arrays like `JSUint8Array` | Typed lists from `dart:typed_data` |
| `JSBoxedDartObject` | Opaque Dart value |
+| `ExternalDartReference` | Opaque Dart value |
{:.table .table-striped}
@@ -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()
@@ -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
@@ -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
@@ -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
\ No newline at end of file
+[#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
\ No newline at end of file