[dart:js_interop/_unsafe] Clean up API docs

- Rephrase docs on JS types
- JS -> JavaScript where applicable
- “This” and “that” expanded to refer to the thing
- Add docs to undocumented members
- Rephrase some docs to be clearer and more explicit
- Move warnings to format that dartdoc can display specially
- Add warnings to every single member that should have it
- e.g. -> like
- Makes similar docs consistent
- Removes library declarations per style guide. Regenerates
  expectations to handle the change.

CoreLibraryReviewExempt: Backend-specific library. Docs only.
Change-Id: I246f8c20d594741149766e5a76bb186debf54ded
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/352977
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Srujan Gaddam <srujzs@google.com>
Reviewed-by: Lasse Nielsen <lrn@google.com>
diff --git a/pkg/front_end/testcases/dart2js/extension_types/external.dart.weak.outline.expect b/pkg/front_end/testcases/dart2js/extension_types/external.dart.weak.outline.expect
index 5f6af44..1c181a0 100644
--- a/pkg/front_end/testcases/dart2js/extension_types/external.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/dart2js/extension_types/external.dart.weak.outline.expect
@@ -1,4 +1,4 @@
-@dart.js_interop::JS::•()
+@#lib1::JS::•()
 library static_interop;
 import self as self;
 import "dart:js_interop" as js_;
diff --git a/pkg/front_end/testcases/dart2js/js_interop_transforms/isa.dart.weak.outline.expect b/pkg/front_end/testcases/dart2js/js_interop_transforms/isa.dart.weak.outline.expect
index 8b02920..a4efeeb 100644
--- a/pkg/front_end/testcases/dart2js/js_interop_transforms/isa.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/dart2js/js_interop_transforms/isa.dart.weak.outline.expect
@@ -1,4 +1,4 @@
-@dart.js_interop::JS::•("library1")
+@#lib1::JS::•("library1")
 library;
 import self as self;
 import "dart:js_interop" as js_;
diff --git a/pkg/front_end/testcases/dartdevc/extension_types/external.dart.weak.outline.expect b/pkg/front_end/testcases/dartdevc/extension_types/external.dart.weak.outline.expect
index 5f6af44..1c181a0 100644
--- a/pkg/front_end/testcases/dartdevc/extension_types/external.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/dartdevc/extension_types/external.dart.weak.outline.expect
@@ -1,4 +1,4 @@
-@dart.js_interop::JS::•()
+@#lib1::JS::•()
 library static_interop;
 import self as self;
 import "dart:js_interop" as js_;
diff --git a/pkg/front_end/testcases/dartdevc/js_interop_transforms/isa.dart.weak.outline.expect b/pkg/front_end/testcases/dartdevc/js_interop_transforms/isa.dart.weak.outline.expect
index 36024fa..83ada2d 100644
--- a/pkg/front_end/testcases/dartdevc/js_interop_transforms/isa.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/dartdevc/js_interop_transforms/isa.dart.weak.outline.expect
@@ -1,4 +1,4 @@
-@dart.js_interop::JS::•("library1")
+@#lib1::JS::•("library1")
 library;
 import self as self;
 import "dart:js_interop" as js_;
diff --git a/sdk/lib/js_interop/js_interop.dart b/sdk/lib/js_interop/js_interop.dart
index 9d47ea8..c8bf548 100644
--- a/sdk/lib/js_interop/js_interop.dart
+++ b/sdk/lib/js_interop/js_interop.dart
@@ -2,10 +2,24 @@
 // 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.
 
-/// Interoperability with JavaScript and browser APIs.
+/// Interoperability, "interop" for short, with JavaScript and browser APIs.
 ///
-/// The [JSObject] type hierarchy is modeled after the JavaScript
-/// type hierarchy, and facilitates sound interoperability with JavaScript.
+/// JavaScript interop allows a Dart program to interact with a JavaScript
+/// runtime. This can, for example, be to access JavaScript declarations and
+/// interact with JavaScript values, or to adapt Dart values so that they can be
+/// passed to and used by JavaScript code.
+///
+/// This JavaScript interop library works by introducing an abstraction over
+/// JavaScript values, a Dart type hierarchy ("JS types") which mirrors known
+/// JavaScript types, and a framework for introducing new Dart types that bind
+/// Dart type declarations to JavaScript values and external member declarations
+/// to JavaScript APIs.
+///
+/// This abstraction allows the same interop API to be used both when the Dart
+/// code is compiled to JavaScript and when compiled to Wasm.
+///
+/// See https://dart.dev/interop/js-interop for more details on usage, types,
+/// and previous JavaScript interop.
 ///
 /// > [!NOTE]
 /// > The types defined in this library only provide static guarantees.
@@ -14,84 +28,106 @@
 /// > and not runtime mechanisms like type checks (`is`) and casts (`as`).
 ///
 /// {@category Web}
-library dart.js_interop;
+library;
 
-import "dart:_internal" show Since;
+import 'dart:_internal' show Since;
+import 'dart:_js_annotations' show JSExport;
 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.
+// To support an easier transition, we allow users to use `@staticInterop`
+// classes - with or without the `@anonymous` annotation.
 export 'dart:_js_annotations' show staticInterop, anonymous, JSExport;
 export 'dart:js_util' show NullRejectionException;
 
-/// The annotation for JS interop members.
+/// An annotation on a JavaScript interop declaration.
 ///
-/// This is meant to signify that a given library, top-level external member, or
-/// extension type is a JS interop declaration.
+/// This annotation defines a given library, top-level external declaration, or
+/// extension type as a JavaScript interop declaration.
 ///
-/// Specifying [name] customizes the JavaScript name to use. This can be used in
-/// the following scenarios:
+/// Specifying [name] customizes the JavaScript name to use, which can be used
+/// in the following scenarios:
 ///
-/// - Namespacing all the external top-level members, static members, and
-///   constructors of a library by annotating the library with a custom name.
-/// - Namespacing all the external static members and constructors of an
-///   extension type by annotating the extension type with a custom name.
-/// - Renaming external members by annotating the member with a custom name.
+/// - Adding a JavaScript prefix to all the external top-level declarations,
+///   static members, and constructors of a library by parameterizing the
+///   annotation on the library with [name].
+/// - Specifying the JavaScript class to use for external static members and
+///   constructors of an interop extension type by parameterizing the annotation
+///   on the interop extension type with [name].
+/// - Renaming external declarations by parameterizing the annotation on the
+///   member with [name].
 ///
-/// In the case where [name] is not specified, we default to the Dart name of
-/// the extension type and external members.
+/// In the case where [name] is not specified, the Dart name of the extension
+/// type or external declaration is used as the default.
 ///
-/// Note: `package:js` exports an `@JS` annotation as well. Unlike that
-/// annotation, this is meant for extension types, and will result in more
-/// type-checking for external top-level members.
+/// See https://dart.dev/interop/js-interop/usage#js for more details on how to
+/// use this annotation.
+///
+/// > [!NOTE]
+/// > `package:js` exports an `@JS` annotation as well. Unlike that annotation,
+/// > this annotation applies to extension types, and will result in more
+/// > type-checking for external top-level declarations.
 class JS {
   final String? name;
   const JS([this.name]);
 }
 
-/// The overall top type in the JS types hierarchy.
+/// A non-nullish JavaScript value.
+///
+/// A [JSAny] can be any JavaScript value except JavaScript `null` and
+/// `undefined`. JavaScript `null` and `undefined` are instead converted to Dart
+/// `null` by the compiler. Therefore, <code>[JSAny]?</code> is the top type of
+/// the type hierarchy as it includes nullish JavaScript values as well.
 extension type JSAny._(JSAnyRepType _jsAny) implements Object {}
 
-/// The representation type of all JavaScript objects for extension types.
+/// A JavaScript `Object`.
 ///
-/// This is the supertype of all JS objects, but not other JS types, like
-/// primitives. See https://dart.dev/interop/js-interop for more details on how
-/// to use JS interop.
+/// [JSObject] is the supertype of all JavaScript objects, but not other JS
+/// types, like primitives. See https://dart.dev/interop/js-interop for more
+/// details on how to use JavaScript interop.
+///
+/// When declaring interop extension types, [JSObject] is usually the type you
+/// will use as the representation type.
 @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].
+  /// Creates a [JSObject] from an object provided by an earlier interop
+  /// library.
   ///
-  /// This constructor and the public representation field are intended to allow
-  /// users to avoid having to cast to and from [JSObject].
+  /// Accepts, for example, the types created using `package:js` or `dart:html`.
+  ///
+  /// This constructor is intended to allow users to avoid having to cast to and
+  /// from [JSObject].
   JSObject.fromInteropObject(Object interopObject)
       : _jsObject = interopObject as JSObjectRepType;
 
-  /// Creates a new JavaScript object.
+  /// Creates a new empty JavaScript object.
+  ///
+  /// The object is created using the JavaScript object initializer syntax
+  /// (`{}`), and this constructor is more efficient than `{}.jsify()`.
   JSObject() : _jsObject = _createObjectLiteral();
 }
 
-// TODO(srujzs): Move this to `JSObject` once we can patch extension type
+// TODO(srujzs): Move this member to `JSObject` once we can patch extension type
 // members.
 external JSObjectRepType _createObjectLiteral();
 
-/// The type of all JS functions.
+/// A JavaScript [`Function`](https://tc39.es/ecma262/#sec-function-objects)
+/// value.
 @JS('Function')
 extension type JSFunction._(JSFunctionRepType _jsFunction)
     implements JSObject {}
 
 /// 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.
+/// See [FunctionToJSExportedDartFunction.toJS] for more details on how to
+/// convert a Dart function.
 @JS('Function')
 extension type JSExportedDartFunction._(
         JSExportedDartFunctionRepType _jsExportedDartFunction)
     implements JSFunction {}
 
-/// The type of all JS arrays.
+/// A JavaScript [`Array`](https://tc39.es/ecma262/#sec-array-objects).
 ///
 /// Because [JSArray] is an extension type, [T] is only a static guarantee and
 /// the array does not necessarily only contain [T] elements. For example:
@@ -102,8 +138,7 @@
 /// ```
 ///
 /// `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].
+/// [JSNumber] when called.
 ///
 /// [T] may introduce additional checking elsewhere, however. When accessing
 /// elements of [JSArray] with type [T], there is a check to ensure the element
@@ -112,15 +147,19 @@
 @JS('Array')
 extension type JSArray<T extends JSAny?>._(JSArrayRepType _jsArray)
     implements JSObject {
+  /// Creates an empty JavaScript `Array`.
+  ///
+  /// Equivalent to `new Array()` and more efficient than `[].jsify()`.
   external JSArray();
+
+  /// Creates a JavaScript `Array` of size [length] with no elements.
   external JSArray.withLength(int length);
 }
 
 /// 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
-/// only check that this is a [JSPromiseRepType].
+/// the [JSPromise] may not actually resolve to a [T].
 ///
 /// Also like with [JSArray], [T] may introduce additional checking elsewhere.
 /// When converted to a [Future<T>], there is a cast to ensure that the [Future]
@@ -131,104 +170,119 @@
   external JSPromise(JSFunction executor);
 }
 
-/// A boxed Dart object that can be passed to JavaScript safely.
+/// A Dart object that is wrapped with a JavaScript object so that it 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.
+/// Use this interface when you want to pass Dart objects within the same
+/// runtime through JavaScript. There are no usable members in the resulting
+/// [JSBoxedDartObject].
+///
+/// See [ObjectToJSBoxedDartObject.toJSBox] to wrap an arbitrary [Object].
 @JS('Object')
 extension type JSBoxedDartObject._(JSBoxedDartObjectRepType _jsBoxedDartObject)
     implements JSObject {}
 
-/// The JavaScript `ArrayBuffer`.
+/// A JavaScript `ArrayBuffer`.
 @JS('ArrayBuffer')
 extension type JSArrayBuffer._(JSArrayBufferRepType _jsArrayBuffer)
     implements JSObject {}
 
-/// The JavaScript `DataView`.
+/// A JavaScript `DataView`.
 @JS('DataView')
 extension type JSDataView._(JSDataViewRepType _jsDataView)
     implements JSObject {}
 
-/// The abstract supertype of all JS typed arrays.
+/// Abstract supertype of all JavaScript typed arrays.
 extension type JSTypedArray._(JSTypedArrayRepType _jsTypedArray)
     implements JSObject {}
 
-/// The JavaScript `Int8Array`.
+/// A JavaScript `Int8Array`.
 @JS('Int8Array')
 extension type JSInt8Array._(JSInt8ArrayRepType _jsInt8Array)
     implements JSTypedArray {}
 
-/// The JavaScript `Uint8Array`.
+/// A JavaScript `Uint8Array`.
 @JS('Uint8Array')
 extension type JSUint8Array._(JSUint8ArrayRepType _jsUint8Array)
     implements JSTypedArray {}
 
-/// The Javascript `Uint8ClampedArray`.
+/// A JavaScript `Uint8ClampedArray`.
 @JS('Uint8ClampedArray')
 extension type JSUint8ClampedArray._(
     JSUint8ClampedArrayRepType _jsUint8ClampedArray) implements JSTypedArray {}
 
-/// The JavaScript `Int16Array`.
+/// A JavaScript `Int16Array`.
 @JS('Int16Array')
 extension type JSInt16Array._(JSInt16ArrayRepType _jsInt16Array)
     implements JSTypedArray {}
 
-/// The Javascript `Uint16Array`.
+/// A JavaScript `Uint16Array`.
 @JS('Uint16Array')
 extension type JSUint16Array._(JSUint16ArrayRepType _jsUint16Array)
     implements JSTypedArray {}
 
-/// The JavaScript `Int32Array`.
+/// A JavaScript `Int32Array`.
 @JS('Int32Array')
 extension type JSInt32Array._(JSInt32ArrayRepType _jsInt32Array)
     implements JSTypedArray {}
 
-/// The Javascript `Uint32Array`.
+/// A JavaScript `Uint32Array`.
 @JS('Uint32Array')
 extension type JSUint32Array._(JSUint32ArrayRepType _jsUint32Array)
     implements JSTypedArray {}
 
-/// The JavaScript `Float32Array`.
+/// A JavaScript `Float32Array`.
 @JS('Float32Array')
 extension type JSFloat32Array._(JSFloat32ArrayRepType _jsFloat32Array)
     implements JSTypedArray {}
 
-/// The Javascript `Float64Array`.
+/// A JavaScript `Float64Array`.
 @JS('Float64Array')
 extension type JSFloat64Array._(JSFloat64ArrayRepType _jsFloat64Array)
     implements JSTypedArray {}
 
-// The various JS primitive types. Crucially, unlike the Dart type hierarchy,
-// none of these are subtypes of [JSObject], but rather they are logically
+// The various JavaScript primitive types. Crucially, unlike the Dart type
+// hierarchy, none of these types are subtypes of [JSObject]. They are just
 // subtypes of [JSAny].
 
-/// The JavaScript numbers.
+/// A JavaScript number.
 extension type JSNumber._(JSNumberRepType _jsNumber) implements JSAny {}
 
-/// The Javascript booleans.
+/// A JavaScript boolean.
 extension type JSBoolean._(JSBooleanRepType _jsBoolean) implements JSAny {}
 
-/// The JavaScript strings.
+/// A JavaScript string.
 extension type JSString._(JSStringRepType _jsString) implements JSAny {}
 
-/// The JavaScript `Symbol`s.
+/// A JavaScript `Symbol`.
 extension type JSSymbol._(JSSymbolRepType _jsSymbol) implements JSAny {}
 
-/// The JavaScript `BigInt`.
+/// A JavaScript `BigInt`.
 extension type JSBigInt._(JSBigIntRepType _jsBigInt) implements JSAny {}
 
-/// A getter to retrieve the global context that is used in static interop
-/// lowering.
-external JSObject get globalContext;
+/// JS type equivalent for `undefined` for interop member return types.
+///
+/// Prefer using `void` instead of this.
+// TODO(srujzs): Mark this as deprecated. There are no performance costs from
+// using `void`, and we'll likely provide a different way to box `undefined`.
+typedef JSVoid = JSVoidRepType;
 
-/// JS `undefined` and JS `null` are internalized differently based on the
-/// backends. In the JS backends, Dart `null` can actually be JS `undefined` or
-/// JS `null`. In dart2wasm, that's not the case: there's only one Wasm value
-/// `null` can be. Therefore, when we get back JS `null` or JS `undefined`, we
-/// internalize both as Dart `null` in dart2wasm, and when we pass Dart `null`
-/// to an interop API, we pass JS `null`. In the JS backends, Dart `null`
-/// retains its original value when passed back to an interop API. Be wary of
-/// writing code where this distinction between `null` and `undefined` matters.
+/// Helper methods to determine if a value is JavaScript `undefined` or `null`.
+///
+/// > [!NOTE]
+/// > The members within these extensions may throw depending on the platform.
+/// > Do not rely on them to be platform-consistent.
+///
+/// JavaScript `undefined` and JavaScript `null` are internalized differently
+/// based on the backend. When compiling to JavaScript, Dart `null` can actually
+/// be JavaScript `undefined` or JavaScript `null`. When compiling to Wasm,
+/// that's not the case: there's only one Wasm value `null` can be. Therefore,
+/// when an interop API returns JavaScript `null` or JavaScript `undefined`,
+/// they are both converted to Dart `null` when compiling to Wasm, and when you
+/// pass a Dart `null` to an interop API, it is called with JavaScript `null`.
+/// When compiling to JavaScript, Dart `null` retains its original JavaScript
+/// value. Avoid writing code where this distinction between `null` and
+/// `undefined` matters.
 // TODO(srujzs): Investigate what it takes to allow users to distinguish between
 // the two "nullish" values. An annotation-based model where users annotate
 // interop APIs to internalize `undefined` differently seems promising, but does
@@ -236,36 +290,42 @@
 // `List<JSAny?>`. In this case, the implementation of the list wrapper needs to
 // make the decision, not the user.
 extension NullableUndefineableJSAnyExtension on JSAny? {
-  /// Determine if this value corresponds to JS `undefined`.
+  /// Whether this value corresponds to JavaScript `undefined`.
   ///
-  /// **WARNING**: Currently, there isn't a way to distinguish between JS
-  /// `undefined` and JS `null` in dart2wasm. As such, this should only be used
-  /// for code that compiles to JS and will throw on dart2wasm.
+  /// > [!NOTE]
+  /// > Currently, there is no way to distinguish between JavaScript `undefined`
+  /// > and JavaScript `null` when compiling to Wasm. Therefore, this getter
+  /// > should only be used for code that compiles to JavaScript and will throw
+  /// > when compiling to Wasm.
   external bool get isUndefined;
 
-  /// Determine if this value corresponds to JS `null`.
+  /// Whether this value corresponds to JavaScript `null`.
   ///
-  /// **WARNING**: Currently, there isn't a way to distinguish between JS
-  /// `undefined` and JS `null` in dart2wasm. As such, this should only be used
-  /// for code that compiles to JS and will throw on dart2wasm.
+  /// > [!NOTE]
+  /// > Currently, there is no way to distinguish between JavaScript `undefined`
+  /// > and JavaScript `null` when compiling to Wasm. Therefore, this getter
+  /// > should only be used for code that compiles to JavaScript and will throw
+  /// > when compiling to Wasm.
   external bool get isNull;
 
   bool get isUndefinedOrNull => this == null;
   bool get isDefinedAndNotNull => !isUndefinedOrNull;
 }
 
-/// Common utility functions that are useful for any JS value.
+/// Common utility functions that are useful for any JavaScript value.
 extension JSAnyUtilityExtension on JSAny? {
-  /// Returns whether the result of `typeof` on this [JSAny]? is [typeString].
+  /// Whether the result of `typeof` on this <code>[JSAny]?</code> is
+  /// [typeString].
   external bool typeofEquals(String typeString);
 
-  /// Returns whether this [JSAny]? is an `instanceof` [constructor].
+  /// Whether this <code>[JSAny]?</code> is an `instanceof` [constructor].
   external bool instanceof(JSFunction constructor);
 
-  /// Returns whether this [JSAny]? is an `instanceof` the constructor that is
-  /// defined by [constructorName], which is looked up in the [globalContext].
+  /// Whether this <code>[JSAny]?</code> is an `instanceof` the constructor that
+  /// is defined by [constructorName], which is looked up in the
+  /// [globalContext].
   ///
-  /// If [constructorName] contains '.'s, we split the name into several parts
+  /// If [constructorName] contains '.'s, the name is split into several parts
   /// in order to get the constructor. For example, `library1.JSClass` would
   /// involve fetching `library1` off of the [globalContext], and then fetching
   /// `JSClass` off of `library1` to get the constructor.
@@ -283,31 +343,35 @@
     return instanceof(constructor as JSFunction);
   }
 
-  /// Whether this [JSAny]? is the actual JS type that is declared by [T].
+  /// Whether this <code>[JSAny]?</code> is an instance of the JavaScript 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.
   ///
-  /// If [T] is a primitive JS type e.g. [JSString], this uses a `typeof` check
-  /// that corresponds to that primitive type e.g. `typeofEquals('string')`.
+  /// If [T] is a primitive JS type like [JSString], this uses a `typeof` check
+  /// that corresponds to that primitive type like `typeofEquals('string')`.
   ///
-  /// If [T] is a non-primitive JS type e.g. [JSArray] or an interop extension
-  /// type on one, this uses an `instanceof` check using the name or @[JS]
-  /// rename of the given type e.g. `instanceOfString('Array')`. Note that if
-  /// you rename the library using the @[JS] annotation, this uses the rename in
-  /// the `instanceof` check e.g. `instanceOfString('library1.JSClass')`.
+  /// If [T] is a non-primitive JS type like [JSArray] or an interop extension
+  /// type on one, this uses an `instanceof` check using the name or the
+  /// <code>@[JS]</code> rename of the given type like
+  /// `instanceOfString('Array')`. Note that if you rename the library using the
+  /// <code>@[JS]</code> annotation, this uses the rename in the `instanceof`
+  /// check like `instanceOfString('library1.JSClass')`.
   ///
-  /// In order to determine the right value for the `instanceof` check, this
-  /// uses the name or the rename of the extension type. So, if you had an
-  /// interop extension type `JSClass` that wraps `JSArray`, this does an
-  /// `instanceOfString('JSClass')` check and not an `instanceOfString('Array')`
-  /// check.
+  /// To determine the JavaScript constructor to use as the second operand in
+  /// the `instanceof` check, this function uses the JavaScript name associated
+  /// with the extension type, which is either the argument given to the
+  /// <code>@[JS]</code> annotation or the Dart declaration name. So, if you had
+  /// an interop extension type `JSClass` that wraps `JSArray` without a rename,
+  /// this does an `instanceOfString('JSClass')` check and not an
+  /// `instanceOfString('Array')` check.
   ///
   /// There are two exceptions to this rule. The first exception is
-  /// `JSTypedArray`. As `TypedArray` does not exist as a property in JS, this
-  /// does some prototype checking to make `isA<JSTypedArray>` do the right
-  /// thing. The other exception is `JSAny`. If you do a `isA<JSAny>` check, it
-  /// will only do a null-check.
+  /// `JSTypedArray`. As `TypedArray` does not exist as a property in
+  /// JavaScript, this does some prototype checking to make `isA<JSTypedArray>`
+  /// do the right thing. The other exception is `JSAny`. If you do a
+  /// `isA<JSAny>` check, it will only do a null-check.
   ///
   /// Using this method with a [T] that has an object literal constructor will
   /// result in an error as you likely want to use [JSObject] instead.
@@ -317,69 +381,116 @@
   @Since('3.4')
   external bool isA<T extends JSAny?>();
 
-  /// Effectively the inverse of [jsify], [dartify] takes a JavaScript object,
-  /// and converts it to a Dart based object. Only JS primitives, arrays, or
-  /// 'map' like JS objects are supported.
+  /// Converts a JavaScript value to the Dart equivalent if possible.
+  ///
+  /// Effectively the inverse of [NullableObjectUtilExtension.jsify], [dartify]
+  /// takes a JavaScript value and recursively converts it to a Dart object.
+  /// Only JavaScript primitives, `Array`s, typed arrays, and map-like objects
+  /// with string property names are supported.
+  ///
+  /// > [!NOTE]
+  /// > Prefer using the specific conversion method like `toDart` if you know
+  /// > the JavaScript type as this method may perform many type-checks.
+  // TODO(srujzs): We likely need stronger tests for this method to ensure
+  // consistency.
   external Object? dartify();
 }
 
-/// Utility extensions for [Object?].
+/// Common utility functions for <code>[Object]?</code>s.
 extension NullableObjectUtilExtension on Object? {
-  /// Recursively converts a JSON-like collection, or Dart primitive to a
-  /// JavaScript compatible representation.
+  /// Converts a Dart object to the JavaScript equivalent if possible.
+  ///
+  /// Effectively the inverse of [JSAnyUtilityExtension.dartify], [jsify] takes
+  /// a Dart object and recursively converts it to a JavaScript value. Only Dart
+  /// primitives, [Iterable]s, typed lists, and [Map]s are supported.
+  ///
+  /// > [!NOTE]
+  /// > Prefer using the specific conversion method like `toJS` if you know the
+  /// > Dart type as this method may perform many type-checks.
+  // TODO(srujzs): We likely need stronger tests for this method to ensure
+  // consistency.
   external JSAny? jsify();
 }
 
-/// The type of `JSUndefined` when returned from functions. Unlike pure JS,
-/// no actual object will be returned.
-// TODO(srujzs): Should we just remove this? There are no performance costs from
-// using `void`, and we'll likely provide a different way to box `undefined`.
-typedef JSVoid = JSVoidRepType;
-
-// Extension members to support conversions between Dart types and JS types.
-// Not all Dart types can be converted to JS types and vice versa.
-// TODO(joshualitt): We might want to investigate using extension types instead
-// of extension methods for these methods.
-
-/// Conversion from [JSExportedDartFunction] to [Function].
-extension JSExportedDartFunctionToFunction on JSExportedDartFunction {
-  external Function get toDart;
-}
-
-/// Conversion from [Function] to [JSExportedDartFunction].
-extension FunctionToJSExportedDartFunction on Function {
-  external JSExportedDartFunction get toJS;
-}
-
 /// Utility extensions for [JSFunction].
+// TODO(srujzs): We may want to provide a syntax for users to avoid `.call` and
+// directly call the function in JavaScript using `(...)`.
 extension JSFunctionUtilExtension on JSFunction {
-  // Take at most 4 args for consistency with other APIs and relative brevity.
-  // If more are needed, you can declare your own external member. We rename
-  // this function since declaring a `call` member makes a class callable in
-  // Dart. This is convenient, but unlike Dart functions, JS functions
-  // explicitly take a `this` argument (which users can provide `null` for in
-  // the case where the function doesn't need it), which may lead to confusion.
+  /// Call this [JSFunction] using the JavaScript `.call` syntax and returns the
+  /// result.
+  ///
+  /// Takes at most 4 args for consistency with other APIs and relative brevity.
+  /// If more are needed, you can declare your own external member with the same
+  /// syntax.
+  // We rename this function since declaring a `call` member makes a class
+  // callable in Dart. This is convenient, but unlike Dart functions, JavaScript
+  // functions explicitly take a `this` argument (which users can provide `null`
+  // for in the case where the function doesn't need it), which may lead to
+  // confusion.
   // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
   @JS('call')
   external JSAny? callAsFunction(
       [JSAny? thisArg, JSAny? arg1, JSAny? arg2, JSAny? arg3, JSAny? arg4]);
 }
 
-/// Conversion from [JSBoxedDartObject] to [Object].
+// Extension members to support conversions between Dart types and JS types.
+// Not all Dart types can be converted to JS types and vice versa.
+// TODO(srujzs): Move some of these to the associated extension type.
+
+/// Conversions from [JSExportedDartFunction] to [Function].
+extension JSExportedDartFunctionToFunction on JSExportedDartFunction {
+  /// The Dart [Function] that this [JSExportedDartFunction] wrapped.
+  ///
+  /// Must be a wrapped Dart [Function].
+  external Function get toDart;
+}
+
+/// Conversions from [Function] to [JSExportedDartFunction].
+extension FunctionToJSExportedDartFunction on Function {
+  /// A callable JavaScript function that wraps this [Function].
+  ///
+  /// If the static type of the [Function] could not be determined or if
+  /// the static type uses types that are disallowed, the call will fail to
+  /// compile. See
+  /// https://dart.dev/interop/js-interop/js-types#requirements-on-external-declarations-and-function-tojs
+  /// for more details on what types are allowed.
+  external JSExportedDartFunction get toJS;
+}
+
+/// Conversions from [JSBoxedDartObject] to [Object].
 extension JSBoxedDartObjectToObject on JSBoxedDartObject {
+  /// The Dart [Object] that this [JSBoxedDartObjectToObject] wrapped.
+  ///
+  /// Throws an [Exception] if the Dart runtime was not the same as the one in
+  /// which the [Object] was wrapped or if this was not a wrapped Dart [Object].
   external Object get toDart;
 }
 
+/// Conversions from [Object] to [JSBoxedDartObject].
 extension ObjectToJSBoxedDartObject on Object {
+  /// A JavaScript object that wraps this [Object].
+  ///
+  /// There are no usable members in the resulting [JSBoxedDartObject] and you
+  /// may get a new [JSBoxedDartObject] when calling [toJSBox] on the same Dart
+  /// [Object].
   external JSBoxedDartObject get toJSBox;
 }
 
-/// Conversion from [JSPromise] to [Future].
+/// Conversions from [JSPromise] to [Future].
 extension JSPromiseToFuture<T extends JSAny?> on JSPromise<T> {
+  /// A [Future] that either completes with the result of the resolved
+  /// [JSPromise] or propagates the error that the [JSPromise] rejected with.
   external Future<T> get toDart;
 }
 
+/// Conversions from [Future] to [JSPromise] where the [Future] returns a value.
 extension FutureOfJSAnyToJSPromise<T extends JSAny?> on Future<T> {
+  /// A [JSPromise] that either resolves with the result of the completed
+  /// [Future] or rejects with an object that contains its error.
+  ///
+  /// The rejected object contains the original error as a [JSBoxedDartObject]
+  /// in the property `error` and the original stack trace as a [String] in the
+  /// property `stack`.
   JSPromise<T> get toJS {
     return JSPromise<T>((JSFunction resolve, JSFunction reject) {
       this.then((JSAny? value) {
@@ -404,8 +515,15 @@
   }
 }
 
-/// Conversion from [Future] to [JSPromise].
+/// Conversions from [Future] to [JSPromise] where the [Future] does not return
+/// a value.
 extension FutureOfVoidToJSPromise on Future<void> {
+  /// A [JSPromise] that either resolves once this [Future] completes or rejects
+  /// with an object that contains its error.
+  ///
+  /// The rejected object contains the original error as a [JSBoxedDartObject]
+  /// in the property `error` and the original stack trace as a [String] in the
+  /// property `stack`.
   JSPromise get toJS {
     return JSPromise((JSFunction resolve, JSFunction reject) {
       this.then((_) => resolve.callAsFunction(resolve),
@@ -427,305 +545,558 @@
   }
 }
 
-// **WARNING**:
-// Currently, the `toJS` getters on `dart:typed_data` types have inconsistent
-// semantics today between dart2wasm and the JS compilers. dart2wasm copies the
-// contents over, while the JS compilers passes the typed arrays by reference as
-// they are JS typed arrays under the hood. Do not rely on modifications to the
-// Dart type to affect the JS type.
-//
-// All the `toDart` getters on the JS typed arrays will introduce a wrapper
-// around the JS typed array, however. So modifying the Dart type will modify
-// the JS type and vice versa in that case.
-
-/// Conversion from [JSArrayBuffer] to [ByteBuffer].
+/// Conversions from [JSArrayBuffer] to [ByteBuffer].
 extension JSArrayBufferToByteBuffer on JSArrayBuffer {
+  /// Converts this [JSArrayBuffer] to a [ByteBuffer] by either casting or
+  /// wrapping it.
+  ///
+  /// When compiling to JavaScript, [ByteBuffer]s are [JSArrayBuffer]s and this
+  /// operation will be a cast. When compiling to Wasm, a wrapper is introduced.
+  /// Modifications to this [JSArrayBuffer] will affect the [ByteBuffer] and
+  /// vice versa.
   external ByteBuffer get toDart;
 }
 
-/// Conversion from [ByteBuffer] to [JSArrayBuffer].
+/// Conversions from [ByteBuffer] to [JSArrayBuffer].
 extension ByteBufferToJSArrayBuffer on ByteBuffer {
+  /// Converts this [ByteBuffer] to a [JSArrayBuffer] by either casting,
+  /// unwrapping, or cloning the [ByteBuffer].
+  ///
+  /// > [!NOTE]
+  /// > Depending on whether code is compiled to JavaScript or Wasm, this
+  /// > conversion will have different semantics.
+  /// > When compiling to JavaScript, all typed lists are the equivalent
+  /// > JavaScript typed arrays, and therefore this method simply casts.
+  /// > When compiling to Wasm, this [ByteBuffer] may or may not be a wrapper
+  /// > depending on if it was converted from JavaScript or instantiated in
+  /// > Dart. If it's a wrapper, this method unwraps it. If it's instantiated in
+  /// > Dart, this method clones this [ByteBuffer]'s values into a new
+  /// > [JSArrayBuffer].
+  /// > Avoid assuming that modifications to this [ByteBuffer] will affect the
+  /// > [JSArrayBuffer] and vice versa unless it was instantiated in JavaScript.
   external JSArrayBuffer get toJS;
 }
 
-/// Conversion from [JSDataView] to [ByteData].
+/// Conversions from [JSDataView] to [ByteData].
 extension JSDataViewToByteData on JSDataView {
+  /// Converts this [JSDataView] to a [ByteData] by either casting or wrapping
+  /// it.
+  ///
+  /// When compiling to JavaScript, [ByteData]s are [JSDataView]s and this
+  /// operation will be a cast. When compiling to Wasm, a wrapper is introduced.
+  /// Modifications to this [JSDataView] will affect the [ByteData] and vice
+  /// versa.
   external ByteData get toDart;
 }
 
-/// Conversion from [ByteData] to [JSDataView].
+/// Conversions from [ByteData] to [JSDataView].
 extension ByteDataToJSDataView on ByteData {
+  /// Converts this [ByteData] to a [JSDataView] by either casting, unwrapping,
+  /// or cloning the [ByteData].
+  ///
+  /// > [!NOTE]
+  /// > Depending on whether code is compiled to JavaScript or Wasm, this
+  /// > conversion will have different semantics.
+  /// > When compiling to JavaScript, all typed lists are the equivalent
+  /// > JavaScript typed arrays, and therefore this method simply casts.
+  /// > When compiling to Wasm, this [ByteData] may or may not be a wrapper
+  /// > depending on if it was converted from JavaScript or instantiated in
+  /// > Dart. If it's a wrapper, this method unwraps it. If it's instantiated in
+  /// > Dart, this method clones this [ByteData]'s values into a new
+  /// > [JSDataView].
+  /// > Avoid assuming that modifications to this [ByteData] will affect the
+  /// > [JSDataView] and vice versa unless it was instantiated in JavaScript.
   external JSDataView get toJS;
 }
 
-/// Conversion from [JSInt8Array] to [Int8List].
+/// Conversions from [JSInt8Array] to [Int8List].
 extension JSInt8ArrayToInt8List on JSInt8Array {
+  /// Converts this [JSInt8Array] to a [Int8List] by either casting or wrapping
+  /// it.
+  ///
+  /// When compiling to JavaScript, [Int8List]s are [JSInt8Array]s and this
+  /// operation will be a cast. When compiling to Wasm, a wrapper is introduced.
+  /// Modifications to this [JSInt8Array] will affect the [Int8List] and vice
+  /// versa.
   external Int8List get toDart;
 }
 
-/// Conversion from [Int8List] to [JSInt8Array].
+/// Conversions from [Int8List] to [JSInt8Array].
 extension Int8ListToJSInt8Array on Int8List {
+  /// Converts this [Int8List] to a [JSInt8Array] by either casting,
+  /// unwrapping, or cloning the [Int8List].
+  ///
+  /// > [!NOTE]
+  /// > Depending on whether code is compiled to JavaScript or Wasm, this
+  /// > conversion will have different semantics.
+  /// > When compiling to JavaScript, all typed lists are the equivalent
+  /// > JavaScript typed arrays, and therefore this method simply casts.
+  /// > When compiling to Wasm, this [Int8List] may or may not be a wrapper
+  /// > depending on if it was converted from JavaScript or instantiated in
+  /// > Dart. If it's a wrapper, this method unwraps it. If it's instantiated in
+  /// > Dart, this method clones this [Int8List]'s values into a new
+  /// > [JSInt8Array].
+  /// > Avoid assuming that modifications to this [Int8List] will affect the
+  /// > [JSInt8Array] and vice versa unless it was instantiated in JavaScript.
   external JSInt8Array get toJS;
 }
 
-/// Conversion from [JSUint8Array] to [Uint8List].
+/// Conversions from [JSUint8Array] to [Uint8List].
 extension JSUint8ArrayToUint8List on JSUint8Array {
+  /// Converts this [JSUint8Array] to a [Uint8List] by either casting or
+  /// wrapping it.
+  ///
+  /// When compiling to JavaScript, [Uint8List]s are [JSUint8Array]s and this
+  /// operation will be a cast. When compiling to Wasm, a wrapper is introduced.
+  /// Modifications to this [JSUint8Array] will affect the [Uint8List] and vice
+  /// versa.
   external Uint8List get toDart;
 }
 
-/// Conversion from [Uint8List] to [JSUint8Array].
+/// Conversions from [Uint8List] to [JSUint8Array].
 extension Uint8ListToJSUint8Array on Uint8List {
+  /// Converts this [Uint8List] to a [JSUint8Array] by either casting,
+  /// unwrapping, or cloning the [Uint8List].
+  ///
+  /// > [!NOTE]
+  /// > Depending on whether code is compiled to JavaScript or Wasm, this
+  /// > conversion will have different semantics.
+  /// > When compiling to JavaScript, all typed lists are the equivalent
+  /// > JavaScript typed arrays, and therefore this method simply casts.
+  /// > When compiling to Wasm, this [Uint8List] may or may not be a wrapper
+  /// > depending on if it was converted from JavaScript or instantiated in
+  /// > Dart. If it's a wrapper, this method unwraps it. If it's instantiated in
+  /// > Dart, this method clones this [Uint8List]'s values into a new
+  /// > [JSUint8Array].
+  /// > Avoid assuming that modifications to this [Uint8List] will affect the
+  /// > [JSUint8Array] and vice versa unless it was instantiated in JavaScript.
   external JSUint8Array get toJS;
 }
 
-/// Conversion from [JSUint8ClampedArray] to [Uint8ClampedList].
+/// Conversions from [JSUint8ClampedArray] to [Uint8ClampedList].
 extension JSUint8ClampedArrayToUint8ClampedList on JSUint8ClampedArray {
+  /// Converts this [JSUint8ClampedArray] to a [Uint8ClampedList] by either
+  /// casting or wrapping it.
+  ///
+  /// When compiling to JavaScript, [Uint8ClampedList]s are
+  /// [JSUint8ClampedArray]s and this operation will be a cast. When compiling
+  /// to Wasm, a wrapper is introduced. Modifications to this
+  /// [JSUint8ClampedArray] will affect the [Uint8ClampedList] and vice versa.
   external Uint8ClampedList get toDart;
 }
 
-/// Conversion from [Uint8ClampedList] to [JSUint8ClampedArray].
+/// Conversions from [Uint8ClampedList] to [JSUint8ClampedArray].
 extension Uint8ClampedListToJSUint8ClampedArray on Uint8ClampedList {
+  /// Converts this [Uint8ClampedList] to a [JSUint8ClampedArray] by either
+  /// casting, unwrapping, or cloning the [Uint8ClampedList].
+  ///
+  /// > [!NOTE]
+  /// > Depending on whether code is compiled to JavaScript or Wasm, this
+  /// > conversion will have different semantics.
+  /// > When compiling to JavaScript, all typed lists are the equivalent
+  /// > JavaScript typed arrays, and therefore this method simply casts.
+  /// > When compiling to Wasm, this [Uint8ClampedList] may or may not be a
+  /// > wrapper depending on if it was converted from JavaScript or instantiated
+  /// > in Dart. If it's a wrapper, this method unwraps it. If it's instantiated
+  /// > in Dart, this method clones this [Uint8ClampedList]'s values into a new
+  /// > [JSUint8ClampedArray].
+  /// > Avoid assuming that modifications to this [Uint8ClampedList] will affect
+  /// > the [JSUint8ClampedArray] and vice versa unless it was instantiated in
+  /// > JavaScript.
   external JSUint8ClampedArray get toJS;
 }
 
-/// Conversion from [JSInt16Array] to [Int16List].
+/// Conversions from [JSInt16Array] to [Int16List].
 extension JSInt16ArrayToInt16List on JSInt16Array {
+  /// Converts this [JSInt16Array] to a [Int16List] by either casting or
+  /// wrapping it.
+  ///
+  /// When compiling to JavaScript, [Int16List]s are [JSInt16Array]s and this
+  /// operation will be a cast. When compiling to Wasm, a wrapper is introduced.
+  /// Modifications to this [JSInt16Array] will affect the [Int16List] and vice
+  /// versa.
   external Int16List get toDart;
 }
 
-/// Conversion from [Int16List] to [JSInt16Array].
+/// Conversions from [Int16List] to [JSInt16Array].
 extension Int16ListToJSInt16Array on Int16List {
+  /// Converts this [Int16List] to a [JSInt16Array] by either casting,
+  /// unwrapping, or cloning the [Int16List].
+  ///
+  /// > [!NOTE]
+  /// > Depending on whether code is compiled to JavaScript or Wasm, this
+  /// > conversion will have different semantics.
+  /// > When compiling to JavaScript, all typed lists are the equivalent
+  /// > JavaScript typed arrays, and therefore this method simply casts.
+  /// > When compiling to Wasm, this [Int16List] may or may not be a wrapper
+  /// > depending on if it was converted from JavaScript or instantiated in
+  /// > Dart. If it's a wrapper, this method unwraps it. If it's instantiated in
+  /// > Dart, this method clones this [Int16List]'s values into a new
+  /// > [JSInt16Array].
+  /// > Avoid assuming that modifications to this [Int16List] will affect the
+  /// > [JSInt16Array] and vice versa unless it was instantiated in JavaScript.
   external JSInt16Array get toJS;
 }
 
-/// Conversion from [JSUint16Array] to [Uint16List].
+/// Conversions from [JSUint16Array] to [Uint16List].
 extension JSUint16ArrayToInt16List on JSUint16Array {
+  /// Converts this [JSUint16Array] to a [Uint16List] by either casting or
+  /// wrapping it.
+  ///
+  /// When compiling to JavaScript, [Uint16List]s are [JSUint16Array]s and this
+  /// operation will be a cast. When compiling to Wasm, a wrapper is introduced.
+  /// Modifications to this [JSUint16Array] will affect the [Uint16List] and
+  /// vice versa.
   external Uint16List get toDart;
 }
 
-/// Conversion from [Uint16List] to [JSUint16Array].
+/// Conversions from [Uint16List] to [JSUint16Array].
 extension Uint16ListToJSInt16Array on Uint16List {
+  /// Converts this [Uint16List] to a [JSUint16Array] by either casting,
+  /// unwrapping, or cloning the [Uint16List].
+  ///
+  /// > [!NOTE]
+  /// > Depending on whether code is compiled to JavaScript or Wasm, this
+  /// > conversion will have different semantics.
+  /// > When compiling to JavaScript, all typed lists are the equivalent
+  /// > JavaScript typed arrays, and therefore this method simply casts.
+  /// > When compiling to Wasm, this [Uint16List] may or may not be a wrapper
+  /// > depending on if it was converted from JavaScript or instantiated in
+  /// > Dart. If it's a wrapper, this method unwraps it. If it's instantiated in
+  /// > Dart, this method clones this [Uint16List]'s values into a new
+  /// > [JSUint16Array].
+  /// > Avoid assuming that modifications to this [Uint16List] will affect the
+  /// > [JSUint16Array] and vice versa unless it was instantiated in JavaScript.
   external JSUint16Array get toJS;
 }
 
-/// Conversion from [JSInt32Array] to [Int32List].
+/// Conversions from [JSInt32Array] to [Int32List].
 extension JSInt32ArrayToInt32List on JSInt32Array {
+  /// Converts this [JSInt32Array] to a [Int32List] by either casting or
+  /// wrapping it.
+  ///
+  /// When compiling to JavaScript, [Int32List]s are [JSInt32Array]s and this
+  /// operation will be a cast. When compiling to Wasm, a wrapper is introduced.
+  /// Modifications to this [JSInt32Array] will affect the [Int32List] and vice
+  /// versa.
   external Int32List get toDart;
 }
 
-/// Conversion from [Int32List] to [JSInt32Array].
+/// Conversions from [Int32List] to [JSInt32Array].
 extension Int32ListToJSInt32Array on Int32List {
+  /// Converts this [Int32List] to a [JSInt32Array] by either casting,
+  /// unwrapping, or cloning the [Int32List].
+  ///
+  /// > [!NOTE]
+  /// > Depending on whether code is compiled to JavaScript or Wasm, this
+  /// > conversion will have different semantics.
+  /// > When compiling to JavaScript, all typed lists are the equivalent
+  /// > JavaScript typed arrays, and therefore this method simply casts.
+  /// > When compiling to Wasm, this [Int32List] may or may not be a wrapper
+  /// > depending on if it was converted from JavaScript or instantiated in
+  /// > Dart. If it's a wrapper, this method unwraps it. If it's instantiated in
+  /// > Dart, this method clones this [Int32List]'s values into a new
+  /// > [JSInt32Array].
+  /// > Avoid assuming that modifications to this [Int32List] will affect the
+  /// > [JSInt32Array] and vice versa unless it was instantiated in JavaScript.
   external JSInt32Array get toJS;
 }
 
-/// Conversion from [JSUint32Array] to [Uint32List].
+/// Conversions from [JSUint32Array] to [Uint32List].
 extension JSUint32ArrayToUint32List on JSUint32Array {
+  /// Converts this [JSUint32Array] to a [Uint32List] by either casting or
+  /// wrapping it.
+  ///
+  /// When compiling to JavaScript, [Uint32List]s are [JSUint32Array]s and this
+  /// operation will be a cast. When compiling to Wasm, a wrapper is introduced.
+  /// Modifications to this [JSUint32Array] will affect the [Uint32List] and
+  /// vice versa.
   external Uint32List get toDart;
 }
 
-/// Conversion from [Uint32List] to [JSUint32Array].
+/// Conversions from [Uint32List] to [JSUint32Array].
 extension Uint32ListToJSUint32Array on Uint32List {
+  /// Converts this [Uint32List] to a [JSUint32Array] by either casting,
+  /// unwrapping, or cloning the [Uint32List].
+  ///
+  /// > [!NOTE]
+  /// > Depending on whether code is compiled to JavaScript or Wasm, this
+  /// > conversion will have different semantics.
+  /// > When compiling to JavaScript, all typed lists are the equivalent
+  /// > JavaScript typed arrays, and therefore this method simply casts.
+  /// > When compiling to Wasm, this [Uint32List] may or may not be a wrapper
+  /// > depending on if it was converted from JavaScript or instantiated in
+  /// > Dart. If it's a wrapper, this method unwraps it. If it's instantiated in
+  /// > Dart, this method clones this [Uint32List]'s values into a new
+  /// > [JSUint32Array].
+  /// > Avoid assuming that modifications to this [Uint32List] will affect the
+  /// > [JSUint32Array] and vice versa unless it was instantiated in JavaScript.
   external JSUint32Array get toJS;
 }
 
-/// Conversion from [JSFloat32Array] to [Float32List].
+/// Conversions from [JSFloat32Array] to [Float32List].
 extension JSFloat32ArrayToFloat32List on JSFloat32Array {
+  /// Converts this [JSFloat32Array] to a [Float32List] by either casting or
+  /// wrapping it.
+  ///
+  /// When compiling to JavaScript, [Float32List]s are [JSFloat32Array]s and
+  /// this operation will be a cast. When compiling to Wasm, a wrapper is
+  /// introduced. Modifications to this [JSFloat32Array] will affect the
+  /// [Float32List] and vice versa.
   external Float32List get toDart;
 }
 
-/// Conversion from [Float32List] to [JSFloat32Array].
+/// Conversions from [Float32List] to [JSFloat32Array].
 extension Float32ListToJSFloat32Array on Float32List {
+  /// Converts this [Float32List] to a [JSFloat32Array] by either casting,
+  /// unwrapping, or cloning the [Float32List].
+  ///
+  /// > [!NOTE]
+  /// > Depending on whether code is compiled to JavaScript or Wasm, this
+  /// > conversion will have different semantics.
+  /// > When compiling to JavaScript, all typed lists are the equivalent
+  /// > JavaScript typed arrays, and therefore this method simply casts.
+  /// > When compiling to Wasm, this [Float32List] may or may not be a wrapper
+  /// > depending on if it was converted from JavaScript or instantiated in
+  /// > Dart. If it's a wrapper, this method unwraps it. If it's instantiated in
+  /// > Dart, this method clones this [Float32List]'s values into a new
+  /// > [JSFloat32Array].
+  /// > Avoid assuming that modifications to this [Float32List] will affect the
+  /// > [JSFloat32Array] and vice versa unless it was instantiated in
+  /// > JavaScript.
   external JSFloat32Array get toJS;
 }
 
-/// Conversion from [JSFloat64Array] to [Float64List].
+/// Conversions from [JSFloat64Array] to [Float64List].
 extension JSFloat64ArrayToFloat64List on JSFloat64Array {
+  /// Converts this [JSFloat64Array] to a [Float64List] by either casting or
+  /// wrapping it.
+  ///
+  /// When compiling to JavaScript, [Float64List]s are [JSFloat64Array]s and
+  /// this operation will be a cast. When compiling to Wasm, a wrapper is
+  /// introduced. Modifications to this [JSFloat64Array] will affect the
+  /// [Float64List] and vice versa.
   external Float64List get toDart;
 }
 
-/// Conversion from [Float64List] to [JSFloat64Array].
+/// Conversions from [Float64List] to [JSFloat64Array].
 extension Float64ListToJSFloat64Array on Float64List {
+  /// Converts this [Float64List] to a [JSFloat64Array] by either casting,
+  /// unwrapping, or cloning the [Float64List].
+  ///
+  /// > [!NOTE]
+  /// > Depending on whether code is compiled to JavaScript or Wasm, this
+  /// > conversion will have different semantics.
+  /// > When compiling to JavaScript, all typed lists are the equivalent
+  /// > JavaScript typed arrays, and therefore this method simply casts.
+  /// > When compiling to Wasm, this [Float64List] may or may not be a wrapper
+  /// > depending on if it was converted from JavaScript or instantiated in
+  /// > Dart. If it's a wrapper, this method unwraps it. If it's instantiated in
+  /// > Dart, this method clones this [Float64List]'s values into a new
+  /// > [JSFloat64Array].
+  /// > Avoid assuming that modifications to this [Float64List] will affect the
+  /// > [JSFloat64Array] and vice versa unless it was instantiated in
+  /// > JavaScript.
   external JSFloat64Array get toJS;
 }
 
-/// Conversion from [JSArray] to [List].
+/// Conversions from [JSArray] to [List].
 extension JSArrayToList<T extends JSAny?> on JSArray<T> {
-  /// Returns a list wrapper of the JS array.
+  /// Converts this [JSArray] to a [List] by either casting or wrapping it.
   ///
-  /// Modifying the JS array will modify the returned list and vice versa.
+  /// When compiling to JavaScript, [List]s are [JSArray]s and this will be a
+  /// cast. When compiling to Wasm, a wrapper is introduced. Modifications to
+  /// this [JSArray] will affect the [List] and vice versa. In order to ensure
+  /// type soundness, this method may introduce casts when accessing elements in
+  /// order to ensure they are of type [T].
   external List<T> get toDart;
 }
 
-/// Conversion from [List] to [JSArray].
+/// Conversions from [List] to [JSArray].
 extension ListToJSArray<T extends JSAny?> on List<T> {
-  /// Compiler-specific conversion from list to JS array.
+  /// Converts this [List] to a [JSArray] by either casting, unwrapping, or
+  /// cloning the [List].
   ///
-  /// This is either a pass-by-reference, unwrap, or copy depending on the
-  /// implementation of the given list, and users shouldn't rely on
-  /// modifications to the list to affect the array or vice versa.
+  /// > [!NOTE]
+  /// > Depending on whether code is compiled to JavaScript or Wasm, this
+  /// > conversion will have different semantics.
+  /// > When compiling to JavaScript, the core [List] is a JavaScript `Array`,
+  /// > and therefore this method simply casts. User-defined [List]s are
+  /// > currently unsupported when compiling to JavaScript.
+  /// > When compiling to Wasm, this [List] may or may not be a wrapper
+  /// > depending on if it was converted from JavaScript or instantiated in
+  /// > Dart. If it's a wrapper, this method unwraps it. If it's instantiated in
+  /// > Dart, this method clones this [List]'s values into a new [JSArray].
+  /// > Avoid assuming that modifications to this [List] will affect the
+  /// > [JSArray] and vice versa unless it was instantiated in JavaScript.
   external JSArray<T> get toJS;
 
-  /// Either passes by reference, unwraps, or creates a heavyweight proxy that
-  /// wraps the list.
+  /// Converts this [List] to a [JSArray] by either casting, unwrapping, or
+  /// proxying the [List].
   ///
-  /// Only use this member if you want modifications to the list to also affect
-  /// the JS array and vice versa. In practice, dart2js and DDC will pass lists
-  /// by reference and dart2wasm will add a proxy or unwrap for most lists.
-  ///
-  /// **WARNING**: Do not rely on this to be performant.
+  /// > [!NOTE]
+  /// > Depending on whether code is compiled to JavaScript or Wasm, this
+  /// > conversion will have different semantics.
+  /// > When compiling to JavaScript, the core [List] is a JavaScript `Array`,
+  /// > and therefore this method simply casts. User-defined [List]s are
+  /// > currently unsupported when compiling to JavaScript.
+  /// > When compiling to Wasm, this [List] may or may not be a wrapper
+  /// > depending on if it was converted from JavaScript or instantiated in
+  /// > Dart. If it's a wrapper, this method unwraps it. If it's instantiated in
+  /// > Dart, this method proxies the [List] using a heavyweight `Array`
+  /// > wrapper. Access to the original [List]'s elements may be very
+  /// > unperformant.
+  /// > Modifications to this [List] will affect the [JSArray] and vice versa.
   external JSArray<T> get toJSProxyOrRef;
 }
 
-/// Conversion from [JSNumber] to [double] or [int].
+/// Conversions from [JSNumber] to [double] or [int].
 extension JSNumberToNumber on JSNumber {
-  /// Returns a Dart [double] for the given [JSNumber].
+  /// Converts this [JSNumber] to a [double].
   external double get toDartDouble;
 
-  /// Returns a Dart [int] for the given [JSNumber].
+  /// Converts this [JSNumber] to an [int].
   ///
-  /// If the [JSNumber] is not an integer value, throws.
+  /// If this [JSNumber] is not an integer value, throws.
   external int get toDartInt;
 }
 
-/// Conversion from [double] to [JSNumber].
+/// Conversions from [double] to [JSNumber].
 extension DoubleToJSNumber on double {
+  /// Converts this [double] to a [JSNumber].
   external JSNumber get toJS;
 }
 
-/// Conversion from [num] to [JSNumber].
+/// Conversions from [num] to [JSNumber].
 extension NumToJSExtension on num {
+  /// Converts this [num] to a [JSNumber].
   JSNumber get toJS => DoubleToJSNumber(toDouble()).toJS;
 }
 
-/// Conversion from [JSBoolean] to [bool].
+/// Conversions from [JSBoolean] to [bool].
 extension JSBooleanToBool on JSBoolean {
+  /// Converts this [JSBoolean] to a [bool].
   external bool get toDart;
 }
 
-/// Conversion from [bool] to [JSBoolean].
+/// Conversions from [bool] to [JSBoolean].
 extension BoolToJSBoolean on bool {
+  /// Converts this [bool] to a [JSBoolean].
   external JSBoolean get toJS;
 }
 
-/// Conversion from [JSString] to [String].
+/// Conversions from [JSString] to [String].
 extension JSStringToString on JSString {
+  /// Converts this [JSString] to a [String].
   external String get toDart;
 }
 
-/// Conversion from [String] to [JSString].
+/// Conversions from [String] to [JSString].
 extension StringToJSString on String {
+  /// Converts this [String] to a [JSString].
   external JSString get toJS;
 }
 
-// General-purpose operators.
-//
-// Indexing operators (`[]`, `[]=`) should be declared through operator
-// overloading instead e.g. `external operator int [](int key);`.
+/// General-purpose JavaScript operators.
+///
+/// Indexing operators (`[]`, `[]=`) should be declared through operator
+/// overloading instead like:
+/// ```
+/// external operator int [](int key);
+/// ```
 // TODO(srujzs): Add more as needed. For now, we just expose the ones needed to
 // migrate from `dart:js_util`.
 extension JSAnyOperatorExtension on JSAny? {
   // Arithmetic operators.
 
-  /// Returns the result of '[this] + [any]' in JS.
+  /// The result of <code>[this] + [any]</code> in JavaScript.
   external JSAny add(JSAny? any);
 
-  /// Returns the result of '[this] - [any]' in JS.
+  /// The result of <code>[this] - [any]</code> in JavaScript.
   external JSAny subtract(JSAny? any);
 
-  /// Returns the result of '[this] * [any]' in JS.
+  /// The result of <code>[this] * [any]</code> in JavaScript.
   external JSAny multiply(JSAny? any);
 
-  /// Returns the result of '[this] / [any]' in JS.
+  /// The result of <code>[this] / [any]</code> in JavaScript.
   external JSAny divide(JSAny? any);
 
-  /// Returns the result of '[this] % [any]' in JS.
+  /// The result of <code>[this] % [any]</code> in JavaScript.
   external JSAny modulo(JSAny? any);
 
-  /// Returns the result of '[this] ** [any]' in JS.
+  /// The result of <code>[this] ** [any]</code> in JavaScript.
   external JSAny exponentiate(JSAny? any);
 
   // Comparison operators.
 
-  /// Returns the result of '[this] > [any]' in JS.
+  /// The result of <code>[this] > [any]</code> in JavaScript.
   external JSBoolean greaterThan(JSAny? any);
 
-  /// Returns the result of '[this] >= [any]' in JS.
+  /// The result of <code>[this] >= [any]</code> in JavaScript.
   external JSBoolean greaterThanOrEqualTo(JSAny? any);
 
-  /// Returns the result of '[this] < [any]' in JS.
+  /// The result of <code>[this] < [any]</code> in JavaScript.
   external JSBoolean lessThan(JSAny? any);
 
-  /// Returns the result of '[this] <= [any]' in JS.
+  /// The result of <code>[this] <= [any]</code> in JavaScript.
   external JSBoolean lessThanOrEqualTo(JSAny? any);
 
-  /// Returns the result of '[this] == [any]' in JS.
+  /// The result of <code>[this] == [any]</code> in JavaScript.
   external JSBoolean equals(JSAny? any);
 
-  /// Returns the result of '[this] != [any]' in JS.
+  /// The result of <code>[this] != [any]</code> in JavaScript.
   external JSBoolean notEquals(JSAny? any);
 
-  /// Returns the result of '[this] === [any]' in JS.
+  /// The result of <code>[this] === [any]</code> in JavaScript.
   external JSBoolean strictEquals(JSAny? any);
 
-  /// Returns the result of '[this] !== [any]' in JS.
+  /// The result of <code>[this] !== [any]</code> in JavaScript.
   external JSBoolean strictNotEquals(JSAny? any);
 
   // Bitwise operators.
 
-  /// Returns the result of '[this] >>> [any]' in JS.
+  /// The result of <code>[this] >>> [any]</code> in JavaScript.
   external JSNumber unsignedRightShift(JSAny? any);
 
   // Logical operators.
 
-  /// Returns the result of '[this] && [any]' in JS.
+  /// The result of <code>[this] && [any]</code> in JavaScript.
   external JSAny? and(JSAny? any);
 
-  /// Returns the result of '[this] || [any]' in JS.
+  /// The result of <code>[this] || [any]</code> in JavaScript.
   external JSAny? or(JSAny? any);
 
-  /// Returns the result of '![this]' in JS.
+  /// The result of <code>![this]</code> in JavaScript.
   external bool get not;
 
-  /// Returns the result of '!![this]' in JS.
+  /// The result of <code>!![this]</code> in JavaScript.
   external bool get isTruthy;
 }
 
-// Top-levels.
-
-/// Given a Dart object that is marked "exportable", creates a JS object that
-/// wraps the given Dart object. Look at the `@JSExport` annotation to determine
-/// what constitutes "exportable" for a Dart class. The object literal
-/// will be a map of export names (which are either the written instance member
-/// names or their rename) to their respective Dart instance members.
+/// The global scope that is used to find user-declared interop members.
 ///
 /// For example:
 ///
-/// ```dart
-/// import 'dart:js_interop';
-///
-/// import 'package:expect/expect.dart';
-///
-/// @JSExport()
-/// class ExportCounter {
-///   @JSExport('value')
-///   int counterValue = 0;
-///   String stringify() => counterValue.toString();
-/// }
-///
-/// extension type Counter(JSObject _) {
-///   external int get value;
-///   external set value(int val);
-///   external String stringify();
-/// }
-///
-/// void main() {
-///   var export = ExportCounter();
-///   var counter = Counter(createJSInteropWrapper(export));
-///   export.counterValue = 1;
-///   Expect.equals(counter.value, export.counterValue);
-///   Expect.equals(counter.stringify(), export.stringify());
-/// }
 /// ```
+/// @JS()
+/// external String get name;
+/// ```
+///
+/// Reading `name` will execute JavaScript code like `globalContext.name`.
+///
+/// There are subtle differences depending on the compiler, but in general,
+/// [globalContext] can be treated like JavaScript's `globalThis`.
+external JSObject get globalContext;
+
+/// Given a instance of a Dart class that contains an <code>@[JSExport]</code>
+/// annotation, creates a JavaScript object that wraps the given Dart object.
+///
+/// The object literal will be a map of properties, which are either the written
+/// instance member names or their renames, to callbacks that call the
+/// corresponding Dart instance members.
+///
+/// See https://dart.dev/interop/js-interop/mock for more details on how to
+/// declare classes that can be used in this method.
 external JSObject createJSInteropWrapper<T extends Object>(T dartObject);
 
 // TODO(srujzs): Expose this method when we handle conformance checking for
@@ -738,8 +1109,8 @@
 // external T createJSInteropMock<T extends JSObject, U extends Object>(
 //     U dartMock, [JSObject? proto = null]);
 
-/// Call to dynamically import a JS module with the given [moduleName] using the
-/// JS `import()` syntax.
+/// Dynamically imports a JavaScript module with the given [moduleName] using
+/// the JavaScript `import()` syntax.
 ///
 /// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import
 /// for more details.
diff --git a/sdk/lib/js_interop_unsafe/js_interop_unsafe.dart b/sdk/lib/js_interop_unsafe/js_interop_unsafe.dart
index 3eb4c1f..f5eb186 100644
--- a/sdk/lib/js_interop_unsafe/js_interop_unsafe.dart
+++ b/sdk/lib/js_interop_unsafe/js_interop_unsafe.dart
@@ -9,84 +9,100 @@
 /// except the methods here are extension methods that use JS types. This
 /// allows code using these functions to also be compiled to WebAssembly.
 ///
-/// 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`.
+/// 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.
 ///
-/// As the name suggests, usage of this library *can* be unsafe. This means that
-/// safe usage of these methods cannot necessarily be verified statically.
-/// Prefer using statically analyzable values like constants or literals for
-/// property or method names so that usage can be verified. This library should
-/// be used cautiously and only when the same effect cannot be achieved with
-/// static interop.
+/// > [!NOTE]
+/// > As the name suggests, usage of this library *can* be unsafe. This means
+/// > that safe usage of these methods cannot necessarily be verified
+/// > statically. Prefer using statically analyzable values like constants or
+/// > literals for property or method names so that usage can be verified. This
+/// > library should be used cautiously and only when the same effect cannot be
+/// > achieved with static interop.
 ///
 /// {@category Web}
-library dart.js_interop_unsafe;
+library;
 
 import 'dart:js_interop';
 
+/// Utility methods to check, get, set, and call properties on a [JSObject].
+///
+/// See the [JavaScript specification](https://tc39.es/ecma262/#sec-object-type)
+/// for more details on using properties.
 extension JSObjectUnsafeUtilExtension on JSObject {
-  /// Shorthand helper to check for String properties.
+  /// Shorthand helper for [hasProperty] to check whether this [JSObject]
+  /// contains the property key [property], but takes and returns a Dart value.
   bool has(String property) => hasProperty(property.toJS).toDart;
 
-  /// Whether or not this [JSObject] has a given property.
+  /// Whether or not this [JSObject] contains the property key [property].
   external JSBoolean hasProperty(JSAny property);
 
-  /// Shorthand helper to get String properties.
+  /// Shorthand helper for [getProperty] to get the value of the property key
+  /// [property] of this [JSObject], but takes and returns a Dart value.
   JSAny? operator [](String property) => getProperty(property.toJS);
 
-  /// Gets a given [property] from this [JSObject].
-  external T getProperty<T extends JSAny?>(JSAny property);
+  /// The value of the property key [property] of this [JSObject].
+  external R getProperty<R extends JSAny?>(JSAny property);
 
-  /// Shorthand helper to set String properties.
+  /// Shorthand helper for [setProperty] to write the [value] of the property
+  /// key [property] of this [JSObject], but takes a Dart value.
   void operator []=(String property, JSAny? value) =>
       setProperty(property.toJS, value);
 
-  /// Sets a given [property] with [value] on this [JSObject].
+  /// Write the [value] of property key [property] of this [JSObject].
   external void setProperty(JSAny property, JSAny? value);
 
   external JSAny? _callMethod(JSAny method,
       [JSAny? arg1, JSAny? arg2, JSAny? arg3, JSAny? arg4]);
 
-  /// Calls a method on this [JSObject] with up to four arguments and returns
-  /// the result.
+  /// Calls [method] on this [JSObject] with up to four arguments.
   ///
-  /// TODO(srujzs): This helper doesn't allow passing nulls, as we use null as
-  /// our sentinel to determine if an argument is passed.
-  T callMethod<T extends JSAny?>(JSAny method,
+  /// Returns the result of calling [method], which must be an [R].
+  ///
+  /// This helper doesn't allow passing nulls, as it determines whether an
+  /// argument is passed based on whether it was null or not. Prefer
+  /// [callMethodVarArgs] if you need to pass nulls.
+  R callMethod<R extends JSAny?>(JSAny method,
           [JSAny? arg1, JSAny? arg2, JSAny? arg3, JSAny? arg4]) =>
-      _callMethod(method, arg1, arg2, arg3, arg4) as T;
+      _callMethod(method, arg1, arg2, arg3, arg4) as R;
 
   external JSAny? _callMethodVarArgs(JSAny method, [List<JSAny?>? arguments]);
 
-  /// Calls a method on this [JSObject] with a variable number of arguments and
-  /// returns the result.
-  T callMethodVarArgs<T extends JSAny?>(JSAny method,
+  /// Calls [method] on this [JSObject] with a variable number of [arguments].
+  ///
+  /// Returns the result of calling [method], which must be an [R].
+  R callMethodVarArgs<R extends JSAny?>(JSAny method,
           [List<JSAny?>? arguments]) =>
-      _callMethodVarArgs(method, arguments) as T;
+      _callMethodVarArgs(method, arguments) as R;
 
-  /// Deletes the given property from this [JSObject].
+  /// Deletes the property with key [property] from this [JSObject].
   external JSBoolean delete(JSAny property);
 }
 
+/// Utility methods to call [JSFunction]s as constructors.
 extension JSFunctionUnsafeUtilExtension on JSFunction {
   external JSObject _callAsConstructor(
       [JSAny? arg1, JSAny? arg2, JSAny? arg3, JSAny? arg4]);
 
-  /// Calls this [JSFunction] as a constructor with up to four arguments and
-  /// returns the constructed [JSObject].
+  /// Calls this [JSFunction] as a constructor with up to four arguments.
   ///
-  /// TODO(srujzs): This helper doesn't allow passing nulls, as we use null as
-  /// our sentinel to determine if an argument is passed.
-  T callAsConstructor<T>(
+  /// Returns the constructed object, which must be an [R].
+  ///
+  /// This helper doesn't allow passing nulls, as it determines whether an
+  /// argument is passed based on whether it was null or not. Prefer
+  /// [callAsConstructorVarArgs] if you need to pass nulls.
+  // TODO(srujzs): The type bound should extend `JSObject`.
+  R callAsConstructor<R>(
           [JSAny? arg1, JSAny? arg2, JSAny? arg3, JSAny? arg4]) =>
-      _callAsConstructor(arg1, arg2, arg3, arg4) as T;
+      _callAsConstructor(arg1, arg2, arg3, arg4) as R;
 
   external JSObject _callAsConstructorVarArgs([List<JSAny?>? arguments]);
 
   /// Calls this [JSFunction] as a constructor with a variable number of
-  /// arguments and returns the constructed [JSObject].
-  T callAsConstructorVarArgs<T extends JSObject>([List<JSAny?>? arguments]) =>
-      _callAsConstructorVarArgs(arguments) as T;
+  /// arguments.
+  ///
+  /// Returns the constructed [JSObject], which must be an [R].
+  R callAsConstructorVarArgs<R extends JSObject>([List<JSAny?>? arguments]) =>
+      _callAsConstructorVarArgs(arguments) as R;
 }