From 53056b663e884547a63d05832b572f3e00bdf27a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 7 Feb 2024 01:47:27 +0000 Subject: [PATCH] js_interop[_unsafe]: update library documentation CoreLibraryReviewExempt: just changing web libraries changekind:NO_CODE_CHANGE Change-Id: Idc8ab1865f43f33c3ab0824142b38fa715b1579b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/350520 Auto-Submit: Kevin Moore Reviewed-by: Srujan Gaddam Reviewed-by: Sigmund Cherem Commit-Queue: Kevin Moore Reviewed-by: Lasse Nielsen --- sdk/lib/js_interop/js_interop.dart | 128 ++++++++---------- .../js_interop_unsafe/js_interop_unsafe.dart | 13 +- 2 files changed, 66 insertions(+), 75 deletions(-) diff --git a/sdk/lib/js_interop/js_interop.dart b/sdk/lib/js_interop/js_interop.dart index 7e50e5cec39a..e86dba34f07b 100644 --- a/sdk/lib/js_interop/js_interop.dart +++ b/sdk/lib/js_interop/js_interop.dart @@ -2,14 +2,16 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -/// A library for JS interop. Includes a JS type hierarchy to facilitate sound -/// interop with JS. The JS type hierarchy is modeled after the actual type -/// hierarchy in JS, and not the Dart type hierarchy. +/// Interoperability with JavaScript and browser APIs. /// -/// Note: The JS types defined in this library only provide static guarantees. -/// The runtime types differ based on the backend, so rely on static -/// functionality like the conversion functions e.g. `toJS` and not runtime -/// mechanisms like type checks and casts. +/// The [JSObject] type hierarchy is modeled after the JavaScript +/// type hierarchy, and facilitates sound interoperability with JavaScript. +/// +/// > [!NOTE] +/// > The types defined in this library only provide static guarantees. +/// > The runtime types differ based on the backend, so it is important to rely +/// > on static functionality like the conversion functions, for example `toJS` +/// > and not runtime mechanisms like type checks (`is`) and casts (`as`). /// /// {@category Web} library dart.js_interop; @@ -19,8 +21,8 @@ import 'dart:_js_types'; import 'dart:js_interop_unsafe'; import 'dart:typed_data'; -/// Allow use of `@staticInterop` classes with JS types as well as export -/// functionality. +// Allow use of `@staticInterop` classes with JS types as well as export +// functionality. export 'dart:_js_annotations' show staticInterop, anonymous, JSExport; export 'dart:js_util' show NullRejectionException; @@ -49,37 +51,25 @@ class JS { const JS([this.name]); } -/// The JS types users should use to write their external APIs. -/// -/// These are meant to separate the Dart and JS type hierarchies statically. -/// -/// **WARNING**: -/// The runtime semantics between backends differ and may not be intuitive e.g. -/// casting to [JSString] may give you inconsistent and surprising results -/// depending on the value and the backend. It is preferred to always use the -/// conversion functions e.g. `toJS` and `toDart`. You should always use interop -/// to type-check e.g. `typeofEquals` and `instanceOfString` instead of relying -/// on `is` and `as`, as the latter is backend-dependent. - /// The overall top type in the JS types hierarchy. extension type JSAny._(JSAnyRepType _jsAny) implements Object {} /// The representation type of all JavaScript objects for extension types. /// /// This is the supertype of all JS objects, but not other JS types, like -/// primitives. See https://dart.dev/web/js-interop for more details on how to -/// use JS interop. +/// primitives. See https://dart.dev/interop/js-interop for more details on how +/// to use JS interop. @JS('Object') extension type JSObject._(JSObjectRepType _jsObject) implements JSAny { /// Constructor to go from an object from previous interop, like the types /// from `package:js` or `dart:html`, to [JSObject]. /// - /// This and the public representation field are intended to avoid users - /// having to cast to and from [JSObject]. + /// This constructor and the public representation field are intended to allow + /// users to avoid having to cast to and from [JSObject]. JSObject.fromInteropObject(Object interopObject) : _jsObject = interopObject as JSObjectRepType; - /// Returns a new object literal. + /// Creates a new JavaScript object. JSObject() : _jsObject = _createObjectLiteral(); } @@ -92,8 +82,9 @@ external JSObjectRepType _createObjectLiteral(); extension type JSFunction._(JSFunctionRepType _jsFunction) implements JSObject {} -/// The type of all Dart functions adapted to be callable from JS. We only allow -/// a subset of Dart functions to be callable from JS. +/// A JavaScript callable function created from a Dart function. +/// +/// We only allow a subset of Dart functions to be callable from JS. // TODO(joshualitt): Detail exactly what are the requirements. @JS('Function') extension type JSExportedDartFunction._( @@ -110,8 +101,9 @@ extension type JSExportedDartFunction._( /// external JSArray get array; /// ``` /// -/// We do not check that `array` actually has [JSNumber]s when calling this -/// member. The only check is that `array` is a [JSArrayRepType]. +/// `array` is not actually checked to ensure it contains instances of +/// [JSNumber] when called. The only check is that `array` is an instance of +/// [JSArray]. /// /// [T] may introduce additional checking elsewhere, however. When accessing /// elements of [JSArray] with type [T], there is a check to ensure the element @@ -124,7 +116,7 @@ extension type JSArray._(JSArrayRepType _jsArray) external JSArray.withLength(int length); } -/// The type of JS promises and promise-like objects. +/// A JavaScript `Promise` or a promise-like object. /// /// Because [JSPromise] is an extension type, [T] is only a static guarantee and /// the [JSPromise] may not actually resolve to a [T]. Like with [JSArray], we @@ -139,19 +131,20 @@ extension type JSPromise._(JSPromiseRepType _jsPromise) external JSPromise(JSFunction executor); } -/// The type of the boxed Dart object that can be passed to JS safely. There is -/// no interface specified of this boxed object, and you may get a new box each -/// time you box the same Dart object. +/// A boxed Dart object that can be passed to JavaScript safely. +/// +/// There is no interface specified of this boxed object, and you may get a new +/// box each time you box the same Dart object. @JS('Object') extension type JSBoxedDartObject._(JSBoxedDartObjectRepType _jsBoxedDartObject) implements JSObject {} -/// The type of JS' `ArrayBuffer`. +/// The Javascript `ArrayBuffer`. @JS('ArrayBuffer') extension type JSArrayBuffer._(JSArrayBufferRepType _jsArrayBuffer) implements JSObject {} -/// The type of JS' `DataView`. +/// The Javascript `DataView`. @JS('DataView') extension type JSDataView._(JSDataViewRepType _jsDataView) implements JSObject {} @@ -160,47 +153,47 @@ extension type JSDataView._(JSDataViewRepType _jsDataView) extension type JSTypedArray._(JSTypedArrayRepType _jsTypedArray) implements JSObject {} -/// The type of JS' `Int8Array`. +/// The Javascript `Int8Array`. @JS('Int8Array') extension type JSInt8Array._(JSInt8ArrayRepType _jsInt8Array) implements JSTypedArray {} -/// The type of JS' `Uint8Array`. +/// The Javascript `Uint8Array`. @JS('Uint8Array') extension type JSUint8Array._(JSUint8ArrayRepType _jsUint8Array) implements JSTypedArray {} -/// The type of JS' `Uint8ClampedArray`. +/// The Javascript `Uint8ClampedArray`. @JS('Uint8ClampedArray') extension type JSUint8ClampedArray._( JSUint8ClampedArrayRepType _jsUint8ClampedArray) implements JSTypedArray {} -/// The type of JS' `Int16Array`. +/// The Javascript `Int16Array`. @JS('Int16Array') extension type JSInt16Array._(JSInt16ArrayRepType _jsInt16Array) implements JSTypedArray {} -/// The type of JS' `Uint16Array`. +/// The Javascript `Uint16Array`. @JS('Uint16Array') extension type JSUint16Array._(JSUint16ArrayRepType _jsUint16Array) implements JSTypedArray {} -/// The type of JS' `Int32Array`. +/// The Javascript `Int32Array`. @JS('Int32Array') extension type JSInt32Array._(JSInt32ArrayRepType _jsInt32Array) implements JSTypedArray {} -/// The type of JS' `Uint32Array`. +/// The Javascript `Uint32Array`. @JS('Uint32Array') extension type JSUint32Array._(JSUint32ArrayRepType _jsUint32Array) implements JSTypedArray {} -/// The type of JS' `Float32Array`. +/// The Javascript `Float32Array`. @JS('Float32Array') extension type JSFloat32Array._(JSFloat32ArrayRepType _jsFloat32Array) implements JSTypedArray {} -/// The type of JS' `Float64Array`. +/// The Javascript `Float64Array`. @JS('Float64Array') extension type JSFloat64Array._(JSFloat64ArrayRepType _jsFloat64Array) implements JSTypedArray {} @@ -209,19 +202,19 @@ extension type JSFloat64Array._(JSFloat64ArrayRepType _jsFloat64Array) // none of these are subtypes of [JSObject], but rather they are logically // subtypes of [JSAny]. -/// The type of JS numbers. +/// The Javascript numbers. extension type JSNumber._(JSNumberRepType _jsNumber) implements JSAny {} -/// The type of JS booleans. +/// The Javascript booleans. extension type JSBoolean._(JSBooleanRepType _jsBoolean) implements JSAny {} -/// The type of JS strings. +/// The Javascript strings. extension type JSString._(JSStringRepType _jsString) implements JSAny {} -/// The type of JS `Symbol`s. +/// The Javascript `Symbol`s. extension type JSSymbol._(JSSymbolRepType _jsSymbol) implements JSAny {} -/// The type of JS `BigInt`s. +/// The Javascript `BigInt`. extension type JSBigInt._(JSBigIntRepType _jsBigInt) implements JSAny {} /// A getter to retrieve the global context that is used in static interop @@ -290,8 +283,7 @@ extension JSAnyUtilityExtension on JSAny? { return instanceof(constructor as JSFunction); } - /// Returns whether this [JSAny]? is the actual JS type that is declared by - /// [T]. + /// Whether this [JSAny]? is the actual JS type that is declared by [T]. /// /// This method uses a combination of null, `typeof`, and `instanceof` checks /// in order to do this check. Use this instead of `is` checks. @@ -349,7 +341,7 @@ typedef JSVoid = JSVoidRepType; // TODO(joshualitt): We might want to investigate using extension types instead // of extension methods for these methods. -/// [JSExportedDartFunction] <-> [Function] +/// Conversion from [JSExportedDartFunction] to [Function]. extension JSExportedDartFunctionToFunction on JSExportedDartFunction { external Function get toDart; } @@ -372,7 +364,7 @@ extension JSFunctionUtilExtension on JSFunction { [JSAny? thisArg, JSAny? arg1, JSAny? arg2, JSAny? arg3, JSAny? arg4]); } -/// [JSBoxedDartObject] <-> [Object] +/// Conversion from [JSBoxedDartObject] to [Object]. extension JSBoxedDartObjectToObject on JSBoxedDartObject { external Object get toDart; } @@ -444,7 +436,7 @@ extension FutureOfVoidToJSPromise on Future { // around the JS typed array, however. So modifying the Dart type will modify // the JS type and vice versa in that case. -/// [JSArrayBuffer] <-> [ByteBuffer] +/// Conversion from [JSArrayBuffer] to [ByteBuffer]. extension JSArrayBufferToByteBuffer on JSArrayBuffer { external ByteBuffer get toDart; } @@ -453,7 +445,7 @@ extension ByteBufferToJSArrayBuffer on ByteBuffer { external JSArrayBuffer get toJS; } -/// [JSDataView] <-> [ByteData] +/// Conversion from [JSDataView] to [ByteData]. extension JSDataViewToByteData on JSDataView { external ByteData get toDart; } @@ -462,7 +454,7 @@ extension ByteDataToJSDataView on ByteData { external JSDataView get toJS; } -/// [JSInt8Array] <-> [Int8List] +/// Conversion from [JSInt8Array] to [Int8List]. extension JSInt8ArrayToInt8List on JSInt8Array { external Int8List get toDart; } @@ -471,7 +463,7 @@ extension Int8ListToJSInt8Array on Int8List { external JSInt8Array get toJS; } -/// [JSUint8Array] <-> [Uint8List] +/// Conversion from [JSUint8Array] to [Uint8List]. extension JSUint8ArrayToUint8List on JSUint8Array { external Uint8List get toDart; } @@ -480,7 +472,7 @@ extension Uint8ListToJSUint8Array on Uint8List { external JSUint8Array get toJS; } -/// [JSUint8ClampedArray] <-> [Uint8ClampedList] +/// Conversion from [JSUint8ClampedArray] to [Uint8ClampedList]. extension JSUint8ClampedArrayToUint8ClampedList on JSUint8ClampedArray { external Uint8ClampedList get toDart; } @@ -489,7 +481,7 @@ extension Uint8ClampedListToJSUint8ClampedArray on Uint8ClampedList { external JSUint8ClampedArray get toJS; } -/// [JSInt16Array] <-> [Int16List] +/// Conversion from [JSInt16Array] to [Int16List]. extension JSInt16ArrayToInt16List on JSInt16Array { external Int16List get toDart; } @@ -498,7 +490,7 @@ extension Int16ListToJSInt16Array on Int16List { external JSInt16Array get toJS; } -/// [JSUint16Array] <-> [Uint16List] +/// Conversion from [JSUint16Array] to [Uint16List]. extension JSUint16ArrayToInt16List on JSUint16Array { external Uint16List get toDart; } @@ -507,7 +499,7 @@ extension Uint16ListToJSInt16Array on Uint16List { external JSUint16Array get toJS; } -/// [JSInt32Array] <-> [Int32List] +/// Conversion from [JSInt32Array] to [Int32List]. extension JSInt32ArrayToInt32List on JSInt32Array { external Int32List get toDart; } @@ -516,7 +508,7 @@ extension Int32ListToJSInt32Array on Int32List { external JSInt32Array get toJS; } -/// [JSUint32Array] <-> [Uint32List] +/// Conversion from [JSUint32Array] to [Uint32List]. extension JSUint32ArrayToUint32List on JSUint32Array { external Uint32List get toDart; } @@ -525,7 +517,7 @@ extension Uint32ListToJSUint32Array on Uint32List { external JSUint32Array get toJS; } -/// [JSFloat32Array] <-> [Float32List] +/// Conversion from [JSFloat32Array] to [Float32List]. extension JSFloat32ArrayToFloat32List on JSFloat32Array { external Float32List get toDart; } @@ -534,7 +526,7 @@ extension Float32ListToJSFloat32Array on Float32List { external JSFloat32Array get toJS; } -/// [JSFloat64Array] <-> [Float64List] +/// Conversion from [JSFloat64Array] to [Float64List]. extension JSFloat64ArrayToFloat64List on JSFloat64Array { external Float64List get toDart; } @@ -543,7 +535,7 @@ extension Float64ListToJSFloat64Array on Float64List { external JSFloat64Array get toJS; } -/// [JSArray] <-> [List] +/// Conversion from [JSArray] to [List]. extension JSArrayToList on JSArray { /// Returns a list wrapper of the JS array. /// @@ -591,7 +583,7 @@ extension NumToJSExtension on num { JSNumber get toJS => DoubleToJSNumber(toDouble()).toJS; } -/// [JSBoolean] <-> [bool] +/// Conversion from [JSBoolean] to [bool]. extension JSBooleanToBool on JSBoolean { external bool get toDart; } @@ -600,7 +592,7 @@ extension BoolToJSBoolean on bool { external JSBoolean get toJS; } -/// [JSString] <-> [String] +/// Conversion from [JSString] to [String]. extension JSStringToString on JSString { external String get toDart; } diff --git a/sdk/lib/js_interop_unsafe/js_interop_unsafe.dart b/sdk/lib/js_interop_unsafe/js_interop_unsafe.dart index 6a4df1321379..f58663caa31f 100644 --- a/sdk/lib/js_interop_unsafe/js_interop_unsafe.dart +++ b/sdk/lib/js_interop_unsafe/js_interop_unsafe.dart @@ -2,18 +2,17 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -/// Utility methods to manipulate JS objects dynamically. +/// Utility methods to manipulate JavaScript objects dynamically. /// /// This library is typically meant to be used when the names of properties or /// methods are not known statically. This library is similar to 'dart:js_util', /// except the methods here are extension methods that use JS types. This -/// enables support with dart2wasm. +/// allows code using these functions to also be compiled to WebAssembly. /// -/// In general, we expect people to use 'dart:js_interop' and that this library -/// will be less commonly used. Prefer to write JS interop interfaces and -/// external static interop members using 'dart:js_interop'. The APIs in this -/// library are generally meant to work around issues and help with migration -/// from older JS interop libraries like 'dart:js'. +/// In general, prefer to write JS interop interfaces and +/// external static interop members using 'dart:js_interop'. This library is +/// meant to work around issues and help with migration from older JS interop +/// libraries like 'dart:js'. /// /// As the name suggests, usage of this library *can* be unsafe. This means that /// safe usage of these methods cannot necessarily be verified statically.