From 152cc247e04c6ff1f4c07f3d9e000bccb196d032 Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Mon, 13 Apr 2026 03:44:43 -0700 Subject: [PATCH] [dart2wasm] Split patch files by whether they use JS interop The eventual goal of the `dart2wasm_standalone` platform is to not rely on a JavaScript environment, which requires rewriting everything that currently relies on `js_interop` or `JS()` helpers. Since most of the patches are still written in Dart and we don't want to duplicate that code for the standalone target, this splits patch files by whether they rely on JS-interop or not. The main entrypoint for each patch (e.g. `lib/_internal/wasm/lib/core_patch.dart`) no longer relies on JS-interop and can safely be used in the standalone target. Part files that previously needed to use JS-interop have been moved into separate patches now, which allows us to migrate them incrementally. In some cases, it was easier to add new patch files: - Similar to the split between `boxed_int` and the `toString` helper patch, we now have the same for `boxed_double`. - The functionality to copy from JS typed data wrappers into Dart typed lists wouldn't work with standalone, so I've moved it into a separate method we can patch to be a noop. - `dart:_wasm` exposes APIs to convert between `JSAny` and `externref`. This is part of a public API, but I had to move those declarations into a patch file because they wouldn't work with standalone. Arguably, a separate library (`dart:_wasm_js_interop`?) would be cleaner but it might be fine as long as `dart:_wasm` is experimental? For now, new patch files relying on JS interop are also applied to the standalone target. They are marked with a comment indicating that they need to be migrated though. Change-Id: I583f23f6cc1a3fc7332962292d69f3a7b0327409 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/489660 Reviewed-by: Slava Egorov Reviewed-by: Martin Kustermann Commit-Queue: Martin Kustermann --- sdk/lib/_internal/wasm/lib/boxed_double.dart | 143 +--------------- .../wasm/lib/boxed_double_patch.dart | 155 ++++++++++++++++++ ...nt_to_string.dart => boxed_int_patch.dart} | 2 +- sdk/lib/_internal/wasm/lib/core_patch.dart | 20 --- .../{deferred.dart => deferred_patch.dart} | 14 +- sdk/lib/_internal/wasm/lib/double_patch.dart | 4 +- ..._module.dart => dynamic_module_patch.dart} | 19 ++- .../wasm/lib/internal_json_encode_patch.dart | 16 ++ .../_internal/wasm/lib/internal_patch.dart | 83 ---------- .../_internal/wasm/lib/invoke_main_patch.dart | 52 ++++++ .../wasm/lib/math_externs_patch.dart | 147 +++++++++++++++++ sdk/lib/_internal/wasm/lib/math_patch.dart | 137 +--------------- sdk/lib/_internal/wasm/lib/print_patch.dart | 2 +- sdk/lib/_internal/wasm/lib/regexp_patch.dart | 3 +- .../_internal/wasm/lib/stack_trace_patch.dart | 3 +- .../_internal/wasm/lib/stopwatch_patch.dart | 3 +- sdk/lib/_internal/wasm/lib/typed_data.dart | 100 ++++------- .../wasm/lib/typed_data_copy_from_js.dart | 103 ++++++++++++ sdk/lib/_internal/wasm/lib/uri_patch.dart | 6 +- .../_internal/wasm/lib/wasm_types_patch.dart | 7 +- ...nt_to_string.dart => boxed_int_patch.dart} | 2 +- sdk/lib/_wasm/wasm_types.dart | 11 -- sdk/lib/libraries.json | 122 ++++++++++---- sdk/lib/libraries.yaml | 107 ++++++++---- tests/web/wasm/source_map_simple_test.dart | 20 +-- 25 files changed, 738 insertions(+), 543 deletions(-) create mode 100644 sdk/lib/_internal/wasm/lib/boxed_double_patch.dart rename sdk/lib/_internal/wasm/lib/{boxed_int_to_string.dart => boxed_int_patch.dart} (94%) rename sdk/lib/_internal/wasm/lib/{deferred.dart => deferred_patch.dart} (90%) rename sdk/lib/_internal/wasm/lib/{dynamic_module.dart => dynamic_module_patch.dart} (94%) create mode 100644 sdk/lib/_internal/wasm/lib/internal_json_encode_patch.dart create mode 100644 sdk/lib/_internal/wasm/lib/invoke_main_patch.dart create mode 100644 sdk/lib/_internal/wasm/lib/math_externs_patch.dart create mode 100644 sdk/lib/_internal/wasm/lib/typed_data_copy_from_js.dart rename sdk/lib/_internal/wasm_js_compatibility/lib/{boxed_int_to_string.dart => boxed_int_patch.dart} (95%) diff --git a/sdk/lib/_internal/wasm/lib/boxed_double.dart b/sdk/lib/_internal/wasm/lib/boxed_double.dart index a4cddbb1cdf..728fdd03faa 100644 --- a/sdk/lib/_internal/wasm/lib/boxed_double.dart +++ b/sdk/lib/_internal/wasm/lib/boxed_double.dart @@ -5,8 +5,6 @@ import "dart:_error_utils"; import 'dart:_boxed_int' show intHashCode; import 'dart:_internal' show doubleToIntBits, intBitsToDouble; -import 'dart:_js_helper' show JS; -import 'dart:_string'; import 'dart:_wasm'; @pragma("wasm:entry-point") @@ -332,146 +330,13 @@ final class BoxedDouble implements double { ); static int _cacheEvictIndex = 0; - String toString() { - final int bits = doubleToIntBits(value); + external String toString(); - if (bits == doubleToIntBits(0.0)) return '0.0'; - if (bits == doubleToIntBits(-0.0)) return '-0.0'; - if (bits == doubleToIntBits(1.0)) return '1.0'; - if (bits == doubleToIntBits(-1.0)) return '-1.0'; + external toStringAsFixed(int fractionDigits); - for (int i = 0; i < CACHE_LENGTH; i++) { - // Special cases such as -0.0/0.0 and NaN are never inserted into the - // cache. - if (bits == _cacheKeys[i]) { - return _cacheValues[i]; - } - } - if (isNaN) return "NaN"; - if (isInfinite) { - if (isNegative) return "-Infinity"; - return "Infinity"; - } + external String toStringAsExponential([int? fractionDigits]); - String result = JSStringImpl.fromRefUnchecked( - JS( - 'Function.prototype.call.bind(Number.prototype.toString)', - WasmF64.fromDouble(value), - ), - ); - if (this % 1.0 == 0.0 && result.indexOf('e') == -1) { - result = '$result.0'; - } - // Replace the least recently inserted entry. - _cacheKeys[_cacheEvictIndex] = bits; - _cacheValues[_cacheEvictIndex] = result; - _cacheEvictIndex = (_cacheEvictIndex + 1) & CACHE_MASK; - return result; - } - - String toStringAsFixed(int fractionDigits) { - // See ECMAScript-262, 15.7.4.5 for details. - - // Step 2. - // 0 <= fractionDigits <= 20 - RangeErrorUtils.checkValueBetweenZeroAndPositiveMax( - fractionDigits, - 20, - "fractionDigits", - ); - - // Step 3. - double x = this; - - // Step 4. - if (isNaN) return "NaN"; - if (this == double.infinity) return "Infinity"; - if (this == -double.infinity) return "-Infinity"; - - // Step 5 and 6 skipped. Will be dealt with by native function. - - // Step 7. - if (x >= 1e21 || x <= -1e21) { - return x.toString(); - } - - String result = _toStringAsFixed(fractionDigits); - if (this == 0 && isNegative) return '-$result'; - return result; - } - - String _toStringAsFixed(int fractionDigits) => JSStringImpl.fromRefUnchecked( - JS( - "(d, digits) => d.toFixed(digits)", - value, - fractionDigits.toDouble(), - ), - ); - - String toStringAsExponential([int? fractionDigits]) { - // See ECMAScript-262, 15.7.4.6 for details. - - // The EcmaScript specification checks for NaN and Infinity before looking - // at the fractionDigits. In Dart we are consistent with toStringAsFixed and - // look at the fractionDigits first. - - // Step 7. - if (fractionDigits != null) { - // 0 <= fractionDigits <= 20 - RangeErrorUtils.checkValueBetweenZeroAndPositiveMax( - fractionDigits, - 20, - "fractionDigits", - ); - } - - if (isNaN) return "NaN"; - if (this == double.infinity) return "Infinity"; - if (this == -double.infinity) return "-Infinity"; - - String result = _toStringAsExponential(fractionDigits); - if (this == 0 && isNegative) return '-$result'; - return result; - } - - String _toStringAsExponential(int? fractionDigits) => - JSStringImpl.fromRefUnchecked( - fractionDigits == null - ? JS("d => d.toExponential()", value) - : JS( - "(d, f) => d.toExponential(f)", - value, - fractionDigits.toDouble(), - ), - ); - - String toStringAsPrecision(int precision) { - // See ECMAScript-262, 15.7.4.7 for details. - - // The EcmaScript specification checks for NaN and Infinity before looking - // at the fractionDigits. In Dart we are consistent with toStringAsFixed and - // look at the fractionDigits first. - - // Step 8. - RangeErrorUtils.checkValueInInterval(precision, 1, 21, "precision"); - - if (isNaN) return "NaN"; - if (this == double.infinity) return "Infinity"; - if (this == -double.infinity) return "-Infinity"; - - String result = _toStringAsPrecision(precision); - if (this == 0 && isNegative) return '-$result'; - return result; - } - - String _toStringAsPrecision(int fractionDigits) => - JSStringImpl.fromRefUnchecked( - JS( - "(d, precision) => d.toPrecision(precision)", - value, - fractionDigits.toDouble(), - ), - ); + external String toStringAsPrecision(int precision); // Order is: NaN > Infinity > ... > 0.0 > -0.0 > ... > -Infinity. int compareTo(num other) { diff --git a/sdk/lib/_internal/wasm/lib/boxed_double_patch.dart b/sdk/lib/_internal/wasm/lib/boxed_double_patch.dart new file mode 100644 index 00000000000..6d17641f201 --- /dev/null +++ b/sdk/lib/_internal/wasm/lib/boxed_double_patch.dart @@ -0,0 +1,155 @@ +// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file +// 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. + +import "dart:_internal" show doubleToIntBits, intBitsToDouble, patch; +import 'dart:_js_helper' show JS; +import 'dart:_string'; + +@patch +class BoxedDouble { + @patch + String toString() { + final int bits = doubleToIntBits(value); + + if (bits == doubleToIntBits(0.0)) return '0.0'; + if (bits == doubleToIntBits(-0.0)) return '-0.0'; + if (bits == doubleToIntBits(1.0)) return '1.0'; + if (bits == doubleToIntBits(-1.0)) return '-1.0'; + + for (int i = 0; i < CACHE_LENGTH; i++) { + // Special cases such as -0.0/0.0 and NaN are never inserted into the + // cache. + if (bits == _cacheKeys[i]) { + return _cacheValues[i]; + } + } + if (isNaN) return "NaN"; + if (isInfinite) { + if (isNegative) return "-Infinity"; + return "Infinity"; + } + + String result = JSStringImpl.fromRefUnchecked( + JS( + 'Function.prototype.call.bind(Number.prototype.toString)', + WasmF64.fromDouble(value), + ), + ); + if (this % 1.0 == 0.0 && result.indexOf('e') == -1) { + result = '$result.0'; + } + // Replace the least recently inserted entry. + _cacheKeys[_cacheEvictIndex] = bits; + _cacheValues[_cacheEvictIndex] = result; + _cacheEvictIndex = (_cacheEvictIndex + 1) & CACHE_MASK; + return result; + } + + @patch + String toStringAsFixed(int fractionDigits) { + // See ECMAScript-262, 15.7.4.5 for details. + + // Step 2. + // 0 <= fractionDigits <= 20 + RangeErrorUtils.checkValueBetweenZeroAndPositiveMax( + fractionDigits, + 20, + "fractionDigits", + ); + + // Step 3. + double x = this; + + // Step 4. + if (isNaN) return "NaN"; + if (this == double.infinity) return "Infinity"; + if (this == -double.infinity) return "-Infinity"; + + // Step 5 and 6 skipped. Will be dealt with by native function. + + // Step 7. + if (x >= 1e21 || x <= -1e21) { + return x.toString(); + } + + String result = _toStringAsFixed(fractionDigits); + if (this == 0 && isNegative) return '-$result'; + return result; + } + + String _toStringAsFixed(int fractionDigits) => JSStringImpl.fromRefUnchecked( + JS( + "(d, digits) => d.toFixed(digits)", + value, + fractionDigits.toDouble(), + ), + ); + + @patch + String toStringAsExponential([int? fractionDigits]) { + // See ECMAScript-262, 15.7.4.6 for details. + + // The EcmaScript specification checks for NaN and Infinity before looking + // at the fractionDigits. In Dart we are consistent with toStringAsFixed and + // look at the fractionDigits first. + + // Step 7. + if (fractionDigits != null) { + // 0 <= fractionDigits <= 20 + RangeErrorUtils.checkValueBetweenZeroAndPositiveMax( + fractionDigits, + 20, + "fractionDigits", + ); + } + + if (isNaN) return "NaN"; + if (this == double.infinity) return "Infinity"; + if (this == -double.infinity) return "-Infinity"; + + String result = _toStringAsExponential(fractionDigits); + if (this == 0 && isNegative) return '-$result'; + return result; + } + + String _toStringAsExponential(int? fractionDigits) => + JSStringImpl.fromRefUnchecked( + fractionDigits == null + ? JS("d => d.toExponential()", value) + : JS( + "(d, f) => d.toExponential(f)", + value, + fractionDigits.toDouble(), + ), + ); + + @patch + String toStringAsPrecision(int precision) { + // See ECMAScript-262, 15.7.4.7 for details. + + // The EcmaScript specification checks for NaN and Infinity before looking + // at the fractionDigits. In Dart we are consistent with toStringAsFixed and + // look at the fractionDigits first. + + // Step 8. + RangeErrorUtils.checkValueInInterval(precision, 1, 21, "precision"); + + if (isNaN) return "NaN"; + if (this == double.infinity) return "Infinity"; + if (this == -double.infinity) return "-Infinity"; + + String result = _toStringAsPrecision(precision); + if (this == 0 && isNegative) return '-$result'; + return result; + } + + String _toStringAsPrecision(int fractionDigits) => + JSStringImpl.fromRefUnchecked( + JS( + "(d, precision) => d.toPrecision(precision)", + value, + fractionDigits.toDouble(), + ), + ); +} diff --git a/sdk/lib/_internal/wasm/lib/boxed_int_to_string.dart b/sdk/lib/_internal/wasm/lib/boxed_int_patch.dart similarity index 94% rename from sdk/lib/_internal/wasm/lib/boxed_int_to_string.dart rename to sdk/lib/_internal/wasm/lib/boxed_int_patch.dart index b377b0cb764..ecd933beb20 100644 --- a/sdk/lib/_internal/wasm/lib/boxed_int_to_string.dart +++ b/sdk/lib/_internal/wasm/lib/boxed_int_patch.dart @@ -1,4 +1,4 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file // 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. diff --git a/sdk/lib/_internal/wasm/lib/core_patch.dart b/sdk/lib/_internal/wasm/lib/core_patch.dart index 60beb1b0e5e..98ae3c188a5 100644 --- a/sdk/lib/_internal/wasm/lib/core_patch.dart +++ b/sdk/lib/_internal/wasm/lib/core_patch.dart @@ -31,20 +31,8 @@ import "dart:_internal" import 'dart:_error_utils'; import "dart:_internal" as _internal; -import 'dart:_js_helper' - show - JS, - JSSyntaxRegExp, - quoteStringForRegExp, - jsStringFromDartString, - stringify, - JavaScriptStack, - JSExternWrapperExt; - import 'dart:_list'; -import 'dart:_string' show JSStringImpl, JSStringImplExt; - import "dart:collection" show HashMap, @@ -64,25 +52,17 @@ import 'dart:math' show Random; import "dart:typed_data"; import 'dart:_object_helper'; -import 'dart:_string_helper'; import 'dart:_wasm'; -import 'internal_patch.dart'; - part "closure.dart"; -part "double_patch.dart"; part "errors_patch.dart"; part "function_patch.dart"; part "identical_patch.dart"; part "named_parameters.dart"; part "object_patch.dart"; part "record_patch.dart"; -part "regexp_patch.dart"; -part "stack_trace_patch.dart"; -part "stopwatch_patch.dart"; part "type.dart"; -part "uri_patch.dart"; typedef _Smi = int; // For compatibility with VM patch files diff --git a/sdk/lib/_internal/wasm/lib/deferred.dart b/sdk/lib/_internal/wasm/lib/deferred_patch.dart similarity index 90% rename from sdk/lib/_internal/wasm/lib/deferred.dart rename to sdk/lib/_internal/wasm/lib/deferred_patch.dart index 9d1087facfe..78e5b72d97f 100644 --- a/sdk/lib/_internal/wasm/lib/deferred.dart +++ b/sdk/lib/_internal/wasm/lib/deferred_patch.dart @@ -1,8 +1,18 @@ -// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file // 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. -part of "internal_patch.dart"; +import 'dart:async'; +import 'dart:js_interop' + show + JSPromise, + JSPromiseToFuture, + JSString, + ListToJSArray, + StringToJSString; +import 'dart:_js_helper' show dartifyRaw, JSValue, JSAnyToExternRef; +import 'dart:_string' show JSStringImpl; +import 'dart:_wasm'; /// Contains active futures for any entities (either module names or IDs) /// currently being loaded. diff --git a/sdk/lib/_internal/wasm/lib/double_patch.dart b/sdk/lib/_internal/wasm/lib/double_patch.dart index 37230fdcf95..35fb2111046 100644 --- a/sdk/lib/_internal/wasm/lib/double_patch.dart +++ b/sdk/lib/_internal/wasm/lib/double_patch.dart @@ -2,7 +2,9 @@ // 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. -part of "core_patch.dart"; +import "dart:_internal" show patch; +import 'dart:_js_helper' show JS; +import 'dart:_js_helper'; @patch class double { diff --git a/sdk/lib/_internal/wasm/lib/dynamic_module.dart b/sdk/lib/_internal/wasm/lib/dynamic_module_patch.dart similarity index 94% rename from sdk/lib/_internal/wasm/lib/dynamic_module.dart rename to sdk/lib/_internal/wasm/lib/dynamic_module_patch.dart index b617e9bbde1..849c43e20e7 100644 --- a/sdk/lib/_internal/wasm/lib/dynamic_module.dart +++ b/sdk/lib/_internal/wasm/lib/dynamic_module_patch.dart @@ -1,8 +1,23 @@ -// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file // 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. -part of "internal_patch.dart"; +import 'dart:js_interop' + show + ByteBufferToJSArrayBuffer, + JSArray, + JSFunction, + JSFunctionUtilExtension, + JSString, + JSArrayToList, + JSStringToString, + JSPromise, + JSPromiseToFuture, + ListToJSArray, + StringToJSString; +import 'dart:_js_helper' show dartifyRaw, JSValue, JSAnyToExternRef; +import 'dart:_wasm'; +import 'dart:typed_data' show Uint8List; @pragma("wasm:import", "moduleLoadingHelper.loadDynamicModuleFromUri") external WasmExternRef _loadModuleFromUri( diff --git a/sdk/lib/_internal/wasm/lib/internal_json_encode_patch.dart b/sdk/lib/_internal/wasm/lib/internal_json_encode_patch.dart new file mode 100644 index 00000000000..e30a5e75a9e --- /dev/null +++ b/sdk/lib/_internal/wasm/lib/internal_json_encode_patch.dart @@ -0,0 +1,16 @@ +// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file +// 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. + +import "dart:_js_helper" show JS, jsStringFromDartString, JSExternWrapperExt; +import 'dart:_string' show JSStringImpl; +import 'dart:_wasm'; + +String jsonEncode(String object) => + // Use checked boxing as `JSON.stringify` can be patched by users. + JSStringImpl.fromRef( + JS( + "s => JSON.stringify(s)", + jsStringFromDartString(object).wrappedExternRef, + ), + ); diff --git a/sdk/lib/_internal/wasm/lib/internal_patch.dart b/sdk/lib/_internal/wasm/lib/internal_patch.dart index 43d2751fa4f..cfa9b8033cb 100644 --- a/sdk/lib/_internal/wasm/lib/internal_patch.dart +++ b/sdk/lib/_internal/wasm/lib/internal_patch.dart @@ -2,39 +2,9 @@ // 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. -import 'dart:async'; -import "dart:_js_helper" - show - JS, - JSAnyToExternRef, - jsStringFromDartString, - jsUint8ArrayFromDartUint8List, - JSExternWrapperExt; -import "dart:_js_types" show JSStringImpl; -import 'dart:_string'; -import 'dart:js_interop' - show - ByteBufferToJSArrayBuffer, - JSArray, - JSFunction, - JSFunctionUtilExtension, - JSString, - JSArrayToList, - JSStringToString, - JSPromise, - JSPromiseToFuture, - ListToJSArray, - StringToJSString; -import 'dart:_js_helper' show dartifyRaw, JSValue; -import 'dart:_js_types'; import 'dart:_wasm'; -import 'dart:math'; -import 'dart:typed_data' show Uint8List; part "class_id.dart"; -part "deferred.dart"; -part "dynamic_module.dart"; -part "print_patch.dart"; part "symbol_patch.dart"; // Compilation to Wasm is always fully null safe. @@ -121,59 +91,6 @@ external int doubleToIntBits(double value); @pragma("wasm:intrinsic") external double intBitsToDouble(int value); -@pragma("wasm:prefer-inline") -void _invokeMainArg0(WasmExternRef jsArrayRef, Function() mainMethod) { - mainMethod(); - return; -} - -@pragma("wasm:prefer-inline") -void _invokeMainArg1( - WasmExternRef jsArrayRef, - Function(List) mainMethod, -) { - final jsArray = (JSValue(jsArrayRef) as JSArray).toDart; - final args = [for (final jsValue in jsArray) jsValue.toDart]; - mainMethod(List.unmodifiable(args)); - return; -} - -@pragma("wasm:prefer-inline") -void _invokeMainArg2( - WasmExternRef jsArrayRef, - Function(List, Null) mainMethod, -) { - final jsArray = (JSValue(jsArrayRef) as JSArray).toDart; - final args = [for (final jsValue in jsArray) jsValue.toDart]; - mainMethod(List.unmodifiable(args), null); - return; -} - -// Will be patched in `pkg/dart2wasm/lib/compile.dart` right before TFA. -external void _invokeMainInternal(WasmExternRef jsArray); - -/// Used to invoke the `main` function from JS, printing any exceptions that -/// escape. -@pragma("wasm:export", "\$invokeMain") -void _invokeMain(WasmExternRef jsArrayRef) { - try { - _invokeMainInternal(jsArrayRef); - } catch (e, s) { - print(e); - print(s); - rethrow; - } -} - -String jsonEncode(String object) => - // Use checked boxing as `JSON.stringify` can be patched by users. - JSStringImpl.fromRef( - JS( - "s => JSON.stringify(s)", - jsStringFromDartString(object).wrappedExternRef, - ), - ); - /// Whether to check bounds in [IndexErrorUtils.checkIndex], /// which are used in list and typed data implementations. /// diff --git a/sdk/lib/_internal/wasm/lib/invoke_main_patch.dart b/sdk/lib/_internal/wasm/lib/invoke_main_patch.dart new file mode 100644 index 00000000000..9f2b3cbe2ed --- /dev/null +++ b/sdk/lib/_internal/wasm/lib/invoke_main_patch.dart @@ -0,0 +1,52 @@ +// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:js_interop' + show JSArray, JSArrayToList, JSString, JSStringToString; +import 'dart:_js_helper' show JSValue; +import 'dart:_wasm'; + +@pragma("wasm:prefer-inline") +void _invokeMainArg0(WasmExternRef jsArrayRef, Function() mainMethod) { + mainMethod(); + return; +} + +@pragma("wasm:prefer-inline") +void _invokeMainArg1( + WasmExternRef jsArrayRef, + Function(List) mainMethod, +) { + final jsArray = (JSValue(jsArrayRef) as JSArray).toDart; + final args = [for (final jsValue in jsArray) jsValue.toDart]; + mainMethod(List.unmodifiable(args)); + return; +} + +@pragma("wasm:prefer-inline") +void _invokeMainArg2( + WasmExternRef jsArrayRef, + Function(List, Null) mainMethod, +) { + final jsArray = (JSValue(jsArrayRef) as JSArray).toDart; + final args = [for (final jsValue in jsArray) jsValue.toDart]; + mainMethod(List.unmodifiable(args), null); + return; +} + +// Will be patched in `pkg/dart2wasm/lib/compile.dart` right before TFA. +external void _invokeMainInternal(WasmExternRef jsArray); + +/// Used to invoke the `main` function from JS, printing any exceptions that +/// escape. +@pragma("wasm:export", "\$invokeMain") +void _invokeMain(WasmExternRef jsArrayRef) { + try { + _invokeMainInternal(jsArrayRef); + } catch (e, s) { + print(e); + print(s); + rethrow; + } +} diff --git a/sdk/lib/_internal/wasm/lib/math_externs_patch.dart b/sdk/lib/_internal/wasm/lib/math_externs_patch.dart new file mode 100644 index 00000000000..5fb44db0c1a --- /dev/null +++ b/sdk/lib/_internal/wasm/lib/math_externs_patch.dart @@ -0,0 +1,147 @@ +// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file +// 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. + +import "dart:_error_utils"; +import "dart:_internal" show patch; +import "dart:js_interop"; +import "dart:_js_types" show JSUint8ArrayImpl; +import "dart:_wasm"; + +@patch +double atan2(num a, num b) => _atan2(a.toDouble(), b.toDouble()); +@patch +double sin(num radians) => _sin(radians.toDouble()); +@patch +double cos(num radians) => _cos(radians.toDouble()); +@patch +double tan(num radians) => _tan(radians.toDouble()); +@patch +double acos(num x) => _acos(x.toDouble()); +@patch +double asin(num x) => _asin(x.toDouble()); +@patch +double atan(num x) => _atan(x.toDouble()); +@patch +double sqrt(num x) => x.toDouble().sqrt(); +@patch +double exp(num x) => _exp(x.toDouble()); +@patch +double log(num x) => _log(x.toDouble()); + +@pragma("wasm:import", "Math.pow") +external double _doublePow(double base, double exponent); +@pragma("wasm:import", "Math.atan2") +external double _atan2(double a, double b); +@pragma("wasm:import", "Math.sin") +external double _sin(double x); +@pragma("wasm:import", "Math.cos") +external double _cos(double x); +@pragma("wasm:import", "Math.tan") +external double _tan(double x); +@pragma("wasm:import", "Math.acos") +external double _acos(double x); +@pragma("wasm:import", "Math.asin") +external double _asin(double x); +@pragma("wasm:import", "Math.atan") +external double _atan(double x); +@pragma("wasm:import", "Math.exp") +external double _exp(double x); +@pragma("wasm:import", "Math.log") +external double _log(double x); + +@JS('crypto') +external _JSCrypto get _jsCryptoGetter; + +final _JSCrypto _jsCrypto = _jsCryptoGetter; + +extension type _JSCrypto._(JSObject _jsCrypto) implements JSObject {} + +extension _JSCryptoGetRandomValues on _JSCrypto { + @JS('getRandomValues') + external void getRandomValues(JSUint8Array array); +} + +@JS('Math') +external _JSMath get _jsMathGetter; + +final _JSMath _jsMath = _jsMathGetter; + +extension type _JSMath._(JSObject _jsMath) implements JSObject {} + +extension _JSMathRandom on _JSMath { + @JS('random') + external double random(); +} + +@patch +class _Random { + @patch + static int _initialSeed() { + final low = (_jsMath.random() * 4294967295.0).toInt(); + final high = (_jsMath.random() * 4294967295.0).toInt(); + return ((high << 32) | low); + } +} + +class _SecureRandom implements Random { + final JSUint8ArrayImpl _buffer = JSUint8ArrayImpl(8); + + _SecureRandom() { + // Throw early in constructor if entropy source is not hooked up. + _getBytes(1); + } + + // Return count bytes of entropy as an integer; count <= 8. + int _getBytes(int count) { + final JSUint8ArrayImpl bufferView = JSUint8ArrayImpl.view( + _buffer.buffer, + 0, + count, + ); + + final JSUint8Array bufferViewJS = bufferView.toJS; + _jsCrypto.getRandomValues(bufferViewJS); + + int value = 0; + for (int i = 0; i < count; i += 1) { + value = (value << 8) | bufferView[i]; + } + + return value; + } + + int nextInt(int max) { + RangeErrorUtils.checkValueInInterval( + max, + 1, + _POW2_32, + "max", + "Must be positive and <= 2^32", + ); + final byteCount = + ((max - 1).bitLength + 7) >> 3; // Divide number of bits by 8, round up. + if (byteCount == 0) { + return 0; // Not random if max == 1. + } + var rnd; + var result; + do { + rnd = _getBytes(byteCount); + result = rnd % max; + } while ((rnd - result + max) > (1 << (byteCount << 3))); + return result; + } + + double nextDouble() { + return (_getBytes(7) >> 3) / _POW2_53_D; + } + + bool nextBool() { + return _getBytes(1).isEven; + } + + // Constants used by the algorithm. + static const _POW2_32 = 1 << 32; + static const _POW2_53_D = 1.0 * (1 << 53); +} diff --git a/sdk/lib/_internal/wasm/lib/math_patch.dart b/sdk/lib/_internal/wasm/lib/math_patch.dart index a646ef630eb..ec19fa61bc3 100644 --- a/sdk/lib/_internal/wasm/lib/math_patch.dart +++ b/sdk/lib/_internal/wasm/lib/math_patch.dart @@ -4,8 +4,6 @@ import "dart:_error_utils"; import "dart:_internal" show mix64, patch; -import "dart:_js_types" show JSUint8ArrayImpl; -import "dart:js_interop"; import "dart:_wasm"; /// There are no parts of this patch library. @@ -81,9 +79,6 @@ num pow(num x, num exponent) { return _doublePow(xDouble, exponentDouble); } -@pragma("wasm:import", "Math.pow") -external double _doublePow(double base, double exponent); - int _intPow(int base, int exponent) { // Exponentiation by squaring. int result = 1; @@ -100,46 +95,6 @@ int _intPow(int base, int exponent) { return result; } -@patch -double atan2(num a, num b) => _atan2(a.toDouble(), b.toDouble()); -@patch -double sin(num radians) => _sin(radians.toDouble()); -@patch -double cos(num radians) => _cos(radians.toDouble()); -@patch -double tan(num radians) => _tan(radians.toDouble()); -@patch -double acos(num x) => _acos(x.toDouble()); -@patch -double asin(num x) => _asin(x.toDouble()); -@patch -double atan(num x) => _atan(x.toDouble()); -@patch -double sqrt(num x) => x.toDouble().sqrt(); -@patch -double exp(num x) => _exp(x.toDouble()); -@patch -double log(num x) => _log(x.toDouble()); - -@pragma("wasm:import", "Math.atan2") -external double _atan2(double a, double b); -@pragma("wasm:import", "Math.sin") -external double _sin(double x); -@pragma("wasm:import", "Math.cos") -external double _cos(double x); -@pragma("wasm:import", "Math.tan") -external double _tan(double x); -@pragma("wasm:import", "Math.acos") -external double _acos(double x); -@pragma("wasm:import", "Math.asin") -external double _asin(double x); -@pragma("wasm:import", "Math.atan") -external double _atan(double x); -@pragma("wasm:import", "Math.exp") -external double _exp(double x); -@pragma("wasm:import", "Math.log") -external double _log(double x); - // TODO(iposva): Handle patch methods within a patch class correctly. @patch class Random { @@ -229,11 +184,7 @@ class _Random implements Random { static int _setupSeed(int seed) => mix64(seed); - static int _initialSeed() { - final low = (_jsMath.random() * 4294967295.0).toInt(); - final high = (_jsMath.random() * 4294967295.0).toInt(); - return ((high << 32) | low); - } + external static int _initialSeed(); static int _nextSeed() { // Trigger the PRNG once to change the internal state. @@ -241,89 +192,3 @@ class _Random implements Random { return _prng._stateLow; } } - -@JS('crypto') -external _JSCrypto get _jsCryptoGetter; - -final _JSCrypto _jsCrypto = _jsCryptoGetter; - -extension type _JSCrypto._(JSObject _jsCrypto) implements JSObject {} - -extension _JSCryptoGetRandomValues on _JSCrypto { - @JS('getRandomValues') - external void getRandomValues(JSUint8Array array); -} - -@JS('Math') -external _JSMath get _jsMathGetter; - -final _JSMath _jsMath = _jsMathGetter; - -extension type _JSMath._(JSObject _jsMath) implements JSObject {} - -extension _JSMathRandom on _JSMath { - @JS('random') - external double random(); -} - -class _SecureRandom implements Random { - final JSUint8ArrayImpl _buffer = JSUint8ArrayImpl(8); - - _SecureRandom() { - // Throw early in constructor if entropy source is not hooked up. - _getBytes(1); - } - - // Return count bytes of entropy as an integer; count <= 8. - int _getBytes(int count) { - final JSUint8ArrayImpl bufferView = JSUint8ArrayImpl.view( - _buffer.buffer, - 0, - count, - ); - - final JSUint8Array bufferViewJS = bufferView.toJS; - _jsCrypto.getRandomValues(bufferViewJS); - - int value = 0; - for (int i = 0; i < count; i += 1) { - value = (value << 8) | bufferView[i]; - } - - return value; - } - - int nextInt(int max) { - RangeErrorUtils.checkValueInInterval( - max, - 1, - _POW2_32, - "max", - "Must be positive and <= 2^32", - ); - final byteCount = - ((max - 1).bitLength + 7) >> 3; // Divide number of bits by 8, round up. - if (byteCount == 0) { - return 0; // Not random if max == 1. - } - var rnd; - var result; - do { - rnd = _getBytes(byteCount); - result = rnd % max; - } while ((rnd - result + max) > (1 << (byteCount << 3))); - return result; - } - - double nextDouble() { - return (_getBytes(7) >> 3) / _POW2_53_D; - } - - bool nextBool() { - return _getBytes(1).isEven; - } - - // Constants used by the algorithm. - static const _POW2_32 = 1 << 32; - static const _POW2_53_D = 1.0 * (1 << 53); -} diff --git a/sdk/lib/_internal/wasm/lib/print_patch.dart b/sdk/lib/_internal/wasm/lib/print_patch.dart index b36f9dbaefa..2cb45472d46 100644 --- a/sdk/lib/_internal/wasm/lib/print_patch.dart +++ b/sdk/lib/_internal/wasm/lib/print_patch.dart @@ -2,7 +2,7 @@ // 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. -part of "internal_patch.dart"; +import "dart:_js_helper" show JS, jsStringFromDartString, JSExternWrapperExt; @patch void printToConsole(String line) => JS( diff --git a/sdk/lib/_internal/wasm/lib/regexp_patch.dart b/sdk/lib/_internal/wasm/lib/regexp_patch.dart index d8ffefe43fa..d51539fdf01 100644 --- a/sdk/lib/_internal/wasm/lib/regexp_patch.dart +++ b/sdk/lib/_internal/wasm/lib/regexp_patch.dart @@ -2,7 +2,8 @@ // 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. -part of "core_patch.dart"; +import 'dart:_js_helper' show JSSyntaxRegExp, quoteStringForRegExp; +import 'dart:_internal' show patch; @patch class RegExp { diff --git a/sdk/lib/_internal/wasm/lib/stack_trace_patch.dart b/sdk/lib/_internal/wasm/lib/stack_trace_patch.dart index caff597967c..e68f13a8138 100644 --- a/sdk/lib/_internal/wasm/lib/stack_trace_patch.dart +++ b/sdk/lib/_internal/wasm/lib/stack_trace_patch.dart @@ -2,7 +2,8 @@ // 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. -part of "core_patch.dart"; +import 'dart:_internal' show patch; +import 'dart:_js_helper' show JavaScriptStack; @patch class StackTrace { diff --git a/sdk/lib/_internal/wasm/lib/stopwatch_patch.dart b/sdk/lib/_internal/wasm/lib/stopwatch_patch.dart index 3c8126734da..c640170a20b 100644 --- a/sdk/lib/_internal/wasm/lib/stopwatch_patch.dart +++ b/sdk/lib/_internal/wasm/lib/stopwatch_patch.dart @@ -2,7 +2,8 @@ // 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. -part of "core_patch.dart"; +import 'dart:_internal' show patch; +import 'dart:_js_helper' show JS; @patch class Stopwatch { diff --git a/sdk/lib/_internal/wasm/lib/typed_data.dart b/sdk/lib/_internal/wasm/lib/typed_data.dart index 7af481c7c9c..a34b308e758 100644 --- a/sdk/lib/_internal/wasm/lib/typed_data.dart +++ b/sdk/lib/_internal/wasm/lib/typed_data.dart @@ -28,8 +28,6 @@ import 'dart:_internal' WhereTypeIterable; import 'dart:_simd'; import 'dart:_wasm'; -import 'dart:_js_types'; -import 'dart:_js_helper'; import 'dart:collection' show ListBase; import 'dart:math' show Random; @@ -1923,6 +1921,18 @@ mixin _IntListMixin implements TypedDataList { } } +/// Outside of the standalone build, checks if [from] is a JS typed array and +/// copies contents into a WASM array. +/// +/// Returns whether a copy was made, or false if [from] is not a typed array. +external bool tryCopyExternalIntTypedData( + Iterable from, + _IntListMixin to, + int start, + int skipCount, + int count, +); + mixin _TypedIntListMixin> on _IntListMixin { SpawnedType _createList(int length); @@ -1943,48 +1953,8 @@ mixin _TypedIntListMixin> throw UnsupportedError("Cannot modify an unmodifiable list"); } - if (from is JSIntegerArrayBase) { - // We only add this mixin to typed lists in this library so we know - // `this` is `TypedData`. - final fromTypedData = unsafeCast(from); - - final fromElementSize = fromTypedData.elementSizeInBytes; - if (fromElementSize == 1 && this is WasmI8ArrayBase) { - final destTypedData = unsafeCast(this); - copyToWasmI8Array( - fromTypedData.toJSArrayExternRef()!, - skipCount, - destTypedData.data, - destTypedData.offsetInElements + start, - count, - ); - return; - } - if (fromElementSize == 2 && this is WasmI16ArrayBase) { - final destTypedData = unsafeCast(this); - copyToWasmI16Array( - fromTypedData.toJSArrayExternRef()!, - skipCount, - destTypedData.data, - destTypedData.offsetInElements + start, - count, - ); - return; - } - if (fromElementSize == 4 && this is _WasmI32ArrayBase) { - final destTypedData = unsafeCast<_WasmI32ArrayBase>(this); - copyToWasmI32Array( - fromTypedData.toJSArrayExternRef()!, - skipCount, - destTypedData.data, - destTypedData.offsetInElements + start, - count, - ); - return; - } - - // NOTICE: We currently don't have `JSUint64Array` classes in - // `dart:js_interop`. + if (tryCopyExternalIntTypedData(from, this, start, skipCount, count)) { + return; } if (from is TypedData) { @@ -2375,6 +2345,18 @@ mixin _DoubleListMixin implements TypedDataList { } } +/// Outside of the standalone build, checks if [from] is a JS typed array and +/// copies contents into a WASM array. +/// +/// Returns whether a copy was made, or false if [from] is not a typed array. +external bool tryCopyExternalFloatTypedData( + Iterable from, + _DoubleListMixin to, + int start, + int skipCount, + int count, +); + mixin _TypedDoubleListMixin> on _DoubleListMixin { SpawnedType _createList(int length); @@ -2399,34 +2381,8 @@ mixin _TypedDoubleListMixin> throw UnsupportedError("Cannot modify an unmodifiable list"); } - if (from is JSFloatArrayBase) { - // We only add this mixin to typed lists in this library so we know - // `this` is `TypedData`. - final fromTypedData = unsafeCast(from); - - final fromElementSize = fromTypedData.elementSizeInBytes; - if (fromElementSize == 4 && this is _WasmF32ArrayBase) { - final destTypedData = unsafeCast<_WasmF32ArrayBase>(this); - copyToWasmF32Array( - fromTypedData.toJSArrayExternRef()!, - skipCount, - destTypedData.data, - destTypedData.offsetInElements + start, - count, - ); - return; - } - if (fromElementSize == 8 && this is _WasmF64ArrayBase) { - final destTypedData = unsafeCast<_WasmF64ArrayBase>(this); - copyToWasmF64Array( - fromTypedData.toJSArrayExternRef()!, - skipCount, - destTypedData.data, - destTypedData.offsetInElements + start, - count, - ); - return; - } + if (tryCopyExternalFloatTypedData(from, this, start, skipCount, count)) { + return; } if (from is TypedData) { diff --git a/sdk/lib/_internal/wasm/lib/typed_data_copy_from_js.dart b/sdk/lib/_internal/wasm/lib/typed_data_copy_from_js.dart new file mode 100644 index 00000000000..16b54d67e03 --- /dev/null +++ b/sdk/lib/_internal/wasm/lib/typed_data_copy_from_js.dart @@ -0,0 +1,103 @@ +// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:_internal' show patch, unsafeCast; +import 'dart:_js_types'; +import 'dart:_js_helper'; + +@patch +bool tryCopyExternalIntTypedData( + Iterable from, + _IntListMixin to, + int start, + int skipCount, + int count, +) { + if (from is JSIntegerArrayBase) { + // We only add this mixin to typed lists in this library so we know + // `this` is `TypedData`. + final fromTypedData = unsafeCast(from); + + final fromElementSize = fromTypedData.elementSizeInBytes; + if (fromElementSize == 1 && to is WasmI8ArrayBase) { + final destTypedData = unsafeCast(to); + copyToWasmI8Array( + fromTypedData.toJSArrayExternRef()!, + skipCount, + destTypedData.data, + destTypedData.offsetInElements + start, + count, + ); + return true; + } + if (fromElementSize == 2 && to is WasmI16ArrayBase) { + final destTypedData = unsafeCast(to); + copyToWasmI16Array( + fromTypedData.toJSArrayExternRef()!, + skipCount, + destTypedData.data, + destTypedData.offsetInElements + start, + count, + ); + return true; + } + if (fromElementSize == 4 && to is _WasmI32ArrayBase) { + final destTypedData = unsafeCast<_WasmI32ArrayBase>(to); + copyToWasmI32Array( + fromTypedData.toJSArrayExternRef()!, + skipCount, + destTypedData.data, + destTypedData.offsetInElements + start, + count, + ); + return true; + } + + // NOTICE: We currently don't have `JSUint64Array` classes in + // `dart:js_interop`. + } + + return false; +} + +@patch +bool tryCopyExternalFloatTypedData( + Iterable from, + _DoubleListMixin to, + int start, + int skipCount, + int count, +) { + if (from is JSFloatArrayBase) { + // We only add this mixin to typed lists in this library so we know + // `this` is `TypedData`. + final fromTypedData = unsafeCast(from); + + final fromElementSize = fromTypedData.elementSizeInBytes; + if (fromElementSize == 4 && to is _WasmF32ArrayBase) { + final destTypedData = unsafeCast<_WasmF32ArrayBase>(to); + copyToWasmF32Array( + fromTypedData.toJSArrayExternRef()!, + skipCount, + destTypedData.data, + destTypedData.offsetInElements + start, + count, + ); + return true; + } + if (fromElementSize == 8 && to is _WasmF64ArrayBase) { + final destTypedData = unsafeCast<_WasmF64ArrayBase>(to); + copyToWasmF64Array( + fromTypedData.toJSArrayExternRef()!, + skipCount, + destTypedData.data, + destTypedData.offsetInElements + start, + count, + ); + return true; + } + } + + return false; +} diff --git a/sdk/lib/_internal/wasm/lib/uri_patch.dart b/sdk/lib/_internal/wasm/lib/uri_patch.dart index 9172f6ca5d1..a248e438764 100644 --- a/sdk/lib/_internal/wasm/lib/uri_patch.dart +++ b/sdk/lib/_internal/wasm/lib/uri_patch.dart @@ -2,7 +2,11 @@ // 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. -part of "core_patch.dart"; +import 'dart:_internal' show patch; +import 'dart:_js_helper' show JS; +import 'dart:_string'; +import 'dart:_wasm'; +import 'dart:convert' show Encoding, utf8; @patch class Uri { diff --git a/sdk/lib/_internal/wasm/lib/wasm_types_patch.dart b/sdk/lib/_internal/wasm/lib/wasm_types_patch.dart index 208c3f96c82..98b7d341669 100644 --- a/sdk/lib/_internal/wasm/lib/wasm_types_patch.dart +++ b/sdk/lib/_internal/wasm/lib/wasm_types_patch.dart @@ -2,17 +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. -import "dart:_internal" show patch; import "dart:_js_helper"; import "dart:_wasm"; import "dart:js_interop"; -@patch extension WasmExternRefToJSAny on WasmExternRef { - @patch JSAny get toJS => JSValue.box(this) as JSAny; } -@patch +// Note: We would make this an extension method on JSAny, but external methods +// on JS interop types are assumed to be JS interop functions, not methods that +// are patched in patch files. So instead we just use a plain function here. WasmExternRef? externRefForJSAny(JSAny object) => (object as JSValue).toExternRef; diff --git a/sdk/lib/_internal/wasm_js_compatibility/lib/boxed_int_to_string.dart b/sdk/lib/_internal/wasm_js_compatibility/lib/boxed_int_patch.dart similarity index 95% rename from sdk/lib/_internal/wasm_js_compatibility/lib/boxed_int_to_string.dart rename to sdk/lib/_internal/wasm_js_compatibility/lib/boxed_int_patch.dart index 2e01bf288fe..1560fbb0c80 100644 --- a/sdk/lib/_internal/wasm_js_compatibility/lib/boxed_int_to_string.dart +++ b/sdk/lib/_internal/wasm_js_compatibility/lib/boxed_int_patch.dart @@ -1,4 +1,4 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file // 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. diff --git a/sdk/lib/_wasm/wasm_types.dart b/sdk/lib/_wasm/wasm_types.dart index 0a239d777a0..2bd03f95edf 100644 --- a/sdk/lib/_wasm/wasm_types.dart +++ b/sdk/lib/_wasm/wasm_types.dart @@ -4,8 +4,6 @@ library dart._wasm; -import 'dart:js_interop'; - part 'memory.dart'; // A collection a special Dart types that are mapped directly to Wasm types @@ -787,15 +785,6 @@ extension DoubleWasmInstructions on double { double sqrt() => this.toWasmF64().sqrt().toDouble(); } -extension WasmExternRefToJSAny on WasmExternRef { - external JSAny get toJS; -} - -// Note: We would make this an extension method on JSAny, but external methods -// on JS interop types are assumed to be JS interop functions, not methods that -// are patched in patch files. So instead we just use a plain function here. -external WasmExternRef? externRefForJSAny(JSAny object); - // Tests whether the given object's class is a subclass of T. // // NOTICE: If the object's class is a subtype of T but not a subclass this will diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json index 2079106a588..3da2afb8bde 100644 --- a/sdk/lib/libraries.json +++ b/sdk/lib/libraries.json @@ -144,6 +144,7 @@ "_internal/vm_shared/lib/bigint_patch.dart", "_internal/vm_shared/lib/bool_patch.dart", "_internal/vm_shared/lib/date_patch.dart", + "_internal/wasm/lib/double_patch.dart", "_internal/vm_shared/lib/map_patch.dart", "_internal/vm_shared/lib/null_patch.dart", "_internal/wasm/lib/array_patch.dart", @@ -152,9 +153,13 @@ "_internal/wasm/lib/date_patch_patch.dart", "_internal/wasm/lib/int_common_patch.dart", "_internal/wasm/lib/int_patch.dart", + "_internal/wasm/lib/regexp_patch.dart", + "_internal/wasm/lib/stack_trace_patch.dart", "_internal/wasm/lib/string_buffer_patch.dart", "_internal/wasm/lib/string_patch.dart", + "_internal/wasm/lib/stopwatch_patch.dart", "_internal/wasm/lib/sync_star_patch.dart", + "_internal/wasm/lib/uri_patch.dart", "_internal/wasm/lib/weak_patch.dart" ] }, @@ -173,13 +178,16 @@ }, "_boxed_int": { "uri": "_internal/wasm/lib/boxed_int.dart", - "patches": "_internal/wasm/lib/boxed_int_to_string.dart" + "patches": "_internal/wasm/lib/boxed_int_patch.dart" }, "_string": { "uri": "_internal/wasm/lib/js_string.dart" }, "_typed_data": { - "uri": "_internal/wasm/lib/typed_data.dart" + "uri": "_internal/wasm/lib/typed_data.dart", + "patches": [ + "_internal/wasm/lib/typed_data_copy_from_js.dart" + ] }, "_js_helper": { "uri": "_internal/wasm/lib/js_helper.dart", @@ -208,6 +216,7 @@ "_internal/vm_shared/lib/bigint_patch.dart", "_internal/vm_shared/lib/bool_patch.dart", "_internal/vm_shared/lib/date_patch.dart", + "_internal/wasm/lib/double_patch.dart", "_internal/vm_shared/lib/map_patch.dart", "_internal/vm_shared/lib/null_patch.dart", "_internal/wasm/lib/array_patch.dart", @@ -216,7 +225,11 @@ "_internal/wasm/lib/date_patch_patch.dart", "_internal/wasm/lib/int_common_patch.dart", "_internal/wasm/lib/int_patch.dart", + "_internal/wasm/lib/regexp_patch.dart", + "_internal/wasm/lib/stack_trace_patch.dart", + "_internal/wasm/lib/stopwatch_patch.dart", "_internal/wasm/lib/sync_star_patch.dart", + "_internal/wasm/lib/uri_patch.dart", "_internal/wasm/lib/weak_patch.dart", "_internal/wasm_js_compatibility/lib/string_buffer_patch.dart", "_internal/wasm_js_compatibility/lib/string_patch.dart" @@ -231,7 +244,7 @@ }, "_boxed_int": { "uri": "_internal/wasm/lib/boxed_int.dart", - "patches": "_internal/wasm_js_compatibility/lib/boxed_int_to_string.dart" + "patches": "_internal/wasm_js_compatibility/lib/boxed_int_patch.dart" }, "_string": { "uri": "_internal/wasm/lib/js_string.dart" @@ -272,12 +285,17 @@ "_internal/wasm/lib/array_patch.dart", "_internal/wasm/lib/bigint_patch_patch.dart", "_internal/wasm/lib/core_patch.dart", + "_internal/wasm/lib/double_patch.dart", "_internal/wasm/lib/date_patch_patch.dart", "_internal/wasm/lib/int_common_patch.dart", "_internal/wasm/lib/int_patch.dart", + "_internal/wasm/lib/regexp_patch.dart", + "_internal/wasm/lib/stack_trace_patch.dart", "_internal/wasm/lib/string_buffer_patch.dart", "_internal/wasm/lib/string_patch.dart", + "_internal/wasm/lib/stopwatch_patch.dart", "_internal/wasm/lib/sync_star_patch.dart", + "_internal/wasm/lib/uri_patch.dart", "_internal/wasm/lib/weak_patch.dart" ] }, @@ -287,6 +305,12 @@ "_internal/wasm/lib/convert_patch.dart" ] }, + "developer": { + "uri": "developer/developer.dart", + "patches": [ + "_internal/js_runtime/lib/developer_patch.dart" + ] + }, "typed_data": { "uri": "typed_data/typed_data.dart", "patches": [ @@ -296,19 +320,50 @@ }, "_boxed_int": { "uri": "_internal/wasm/lib/boxed_int.dart", - "patches": "_internal/wasm/lib/boxed_int_to_string.dart" + "patches": "_internal/wasm/lib/boxed_int_patch.dart" + }, + "_boxed_double": { + "uri": "_internal/wasm/lib/boxed_double.dart", + "patches": [ + "_internal/wasm/lib/boxed_double_patch.dart" + ] }, "_string": { "uri": "_internal/wasm/lib/js_string.dart" }, "_typed_data": { - "uri": "_internal/wasm/lib/typed_data.dart" + "uri": "_internal/wasm/lib/typed_data.dart", + "patches": [ + "_internal/wasm/lib/typed_data_copy_from_js.dart" + ] }, "_js_helper": { "uri": "_internal/wasm/lib/js_helper.dart", "patches": [ "_internal/wasm/lib/js_helper_patch.dart" ] + }, + "_internal": { + "uri": "internal/internal.dart", + "patches": [ + "_internal/wasm/lib/internal_patch.dart", + "_internal/wasm/lib/deferred_patch.dart", + "_internal/wasm/lib/dynamic_module_patch.dart", + "_internal/wasm/lib/internal_json_encode_patch.dart", + "_internal/wasm/lib/invoke_main_patch.dart", + "_internal/wasm/lib/print_patch.dart" + ] + }, + "_wasm": { + "uri": "_wasm/wasm_types.dart", + "patches": "_internal/wasm/lib/wasm_types_patch.dart" + }, + "math": { + "uri": "math/math.dart", + "patches": [ + "_internal/wasm/lib/math_patch.dart", + "_internal/wasm/lib/math_externs_patch.dart" + ] } } }, @@ -319,12 +374,46 @@ } ], "libraries": { + "_boxed_double": { + "uri": "_internal/wasm/lib/boxed_double.dart", + "patches": [ + "_internal/wasm/lib/boxed_double_patch.dart" + ] + }, + "_internal": { + "uri": "internal/internal.dart", + "patches": [ + "_internal/wasm/lib/internal_patch.dart", + "_internal/wasm/lib/deferred_patch.dart", + "_internal/wasm/lib/dynamic_module_patch.dart", + "_internal/wasm/lib/internal_json_encode_patch.dart", + "_internal/wasm/lib/invoke_main_patch.dart", + "_internal/wasm/lib/print_patch.dart" + ] + }, + "_wasm": { + "uri": "_wasm/wasm_types.dart", + "patches": "_internal/wasm/lib/wasm_types_patch.dart" + }, "async": { "uri": "async/async.dart", "patches": [ "_internal/wasm/lib/async_patch.dart", "_internal/wasm/lib/timer_patch.dart" ] + }, + "developer": { + "uri": "developer/developer.dart", + "patches": [ + "_internal/js_runtime/lib/developer_patch.dart" + ] + }, + "math": { + "uri": "math/math.dart", + "patches": [ + "_internal/wasm/lib/math_patch.dart", + "_internal/wasm/lib/math_externs_patch.dart" + ] } } }, @@ -342,9 +431,6 @@ "_boxed_int": { "uri": "_internal/wasm/lib/boxed_int.dart" }, - "_boxed_double": { - "uri": "_internal/wasm/lib/boxed_double.dart" - }, "_compact_hash": { "uri": "_internal/wasm/lib/compact_hash.dart" }, @@ -357,12 +443,6 @@ "_internal/js_shared/lib/http_patch.dart" ] }, - "_internal": { - "uri": "internal/internal.dart", - "patches": [ - "_internal/wasm/lib/internal_patch.dart" - ] - }, "_js_string_convert": { "uri": "_internal/wasm/lib/js_string_convert.dart" }, @@ -381,10 +461,6 @@ "_string_helper": { "uri": "_internal/wasm/lib/string_helper.dart" }, - "_wasm": { - "uri": "_wasm/wasm_types.dart", - "patches": "_internal/wasm/lib/wasm_types_patch.dart" - }, "collection": { "uri": "collection/collection.dart", "patches": [ @@ -392,12 +468,6 @@ "_internal/wasm/lib/hash_factories.dart" ] }, - "developer": { - "uri": "developer/developer.dart", - "patches": [ - "_internal/js_runtime/lib/developer_patch.dart" - ] - }, "ffi": { "uri": "ffi/ffi.dart", "patches": [ @@ -430,10 +500,6 @@ "js_interop_unsafe": { "uri": "js_interop_unsafe/js_interop_unsafe.dart", "patches": "_internal/wasm/lib/js_interop_unsafe_patch.dart" - }, - "math": { - "uri": "math/math.dart", - "patches": "_internal/wasm/lib/math_patch.dart" } } }, diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml index 8932fc2558c..8bc73b7555e 100644 --- a/sdk/lib/libraries.yaml +++ b/sdk/lib/libraries.yaml @@ -133,6 +133,7 @@ wasm: - _internal/vm_shared/lib/bigint_patch.dart - _internal/vm_shared/lib/bool_patch.dart - _internal/vm_shared/lib/date_patch.dart + - _internal/wasm/lib/double_patch.dart - _internal/vm_shared/lib/map_patch.dart - _internal/vm_shared/lib/null_patch.dart - _internal/wasm/lib/array_patch.dart @@ -141,9 +142,13 @@ wasm: - _internal/wasm/lib/date_patch_patch.dart - _internal/wasm/lib/int_common_patch.dart - _internal/wasm/lib/int_patch.dart + - _internal/wasm/lib/regexp_patch.dart + - _internal/wasm/lib/stack_trace_patch.dart - _internal/wasm/lib/string_buffer_patch.dart - _internal/wasm/lib/string_patch.dart + - _internal/wasm/lib/stopwatch_patch.dart - _internal/wasm/lib/sync_star_patch.dart + - _internal/wasm/lib/uri_patch.dart - _internal/wasm/lib/weak_patch.dart convert: uri: convert/convert.dart @@ -157,11 +162,13 @@ wasm: _boxed_int: uri: _internal/wasm/lib/boxed_int.dart patches: - _internal/wasm/lib/boxed_int_to_string.dart + _internal/wasm/lib/boxed_int_patch.dart _string: uri: _internal/wasm/lib/js_string.dart _typed_data: uri: _internal/wasm/lib/typed_data.dart + patches: + - _internal/wasm/lib/typed_data_copy_from_js.dart _js_helper: uri: _internal/wasm/lib/js_helper.dart patches: @@ -181,6 +188,7 @@ wasm_js_compatibility: - _internal/vm_shared/lib/bigint_patch.dart - _internal/vm_shared/lib/bool_patch.dart - _internal/vm_shared/lib/date_patch.dart + - _internal/wasm/lib/double_patch.dart - _internal/vm_shared/lib/map_patch.dart - _internal/vm_shared/lib/null_patch.dart - _internal/wasm/lib/array_patch.dart @@ -189,7 +197,11 @@ wasm_js_compatibility: - _internal/wasm/lib/date_patch_patch.dart - _internal/wasm/lib/int_common_patch.dart - _internal/wasm/lib/int_patch.dart + - _internal/wasm/lib/regexp_patch.dart + - _internal/wasm/lib/stack_trace_patch.dart + - _internal/wasm/lib/stopwatch_patch.dart - _internal/wasm/lib/sync_star_patch.dart + - _internal/wasm/lib/uri_patch.dart - _internal/wasm/lib/weak_patch.dart - _internal/wasm_js_compatibility/lib/string_buffer_patch.dart - _internal/wasm_js_compatibility/lib/string_patch.dart @@ -201,7 +213,7 @@ wasm_js_compatibility: _boxed_int: uri: _internal/wasm/lib/boxed_int.dart patches: - _internal/wasm_js_compatibility/lib/boxed_int_to_string.dart + _internal/wasm_js_compatibility/lib/boxed_int_patch.dart _string: uri: _internal/wasm/lib/js_string.dart _js_helper: @@ -220,8 +232,6 @@ wasm_standalone: patches: - _internal/wasm/lib/async_patch.dart - _internal/wasm_standalone/lib/timer_patch.dart - - # Not yet migrated core: uri: core/core.dart patches: @@ -233,17 +243,26 @@ wasm_standalone: - _internal/wasm/lib/array_patch.dart - _internal/wasm/lib/bigint_patch_patch.dart - _internal/wasm/lib/core_patch.dart - - _internal/wasm/lib/date_patch_patch.dart + - _internal/wasm/lib/double_patch.dart # TODO(53884): Rewrite without JS interop in _internal/wasm_standalone + - _internal/wasm/lib/date_patch_patch.dart # TODO(53884): Rewrite without JS interop in _internal/wasm_standalone - _internal/wasm/lib/int_common_patch.dart - _internal/wasm/lib/int_patch.dart - - _internal/wasm/lib/string_buffer_patch.dart - - _internal/wasm/lib/string_patch.dart + - _internal/wasm/lib/regexp_patch.dart # TODO(53884): Rewrite without JS interop in _internal/wasm_standalone + - _internal/wasm/lib/stack_trace_patch.dart # TODO(53884): Rewrite without JS interop in _internal/wasm_standalone + - _internal/wasm/lib/string_buffer_patch.dart # TODO(53884): Rewrite without JS interop in _internal/wasm_standalone + - _internal/wasm/lib/string_patch.dart # TODO(53884): Rewrite without JS interop in _internal/wasm_standalone + - _internal/wasm/lib/stopwatch_patch.dart # TODO(53884): Rewrite without JS interop in _internal/wasm_standalone - _internal/wasm/lib/sync_star_patch.dart - - _internal/wasm/lib/weak_patch.dart + - _internal/wasm/lib/uri_patch.dart # TODO(53884): Rewrite without JS interop in _internal/wasm_standalone + - _internal/wasm/lib/weak_patch.dart # TODO(53884): Rewrite without JS interop in _internal/wasm_standalone convert: uri: convert/convert.dart patches: - - _internal/wasm/lib/convert_patch.dart + - _internal/wasm/lib/convert_patch.dart # TODO(53884): Rewrite without JS interop in _internal/wasm_standalone + developer: + uri: developer/developer.dart + patches: + - _internal/js_runtime/lib/developer_patch.dart # TODO(53884): Rewrite without JS interop in _internal/wasm_standalone typed_data: uri: typed_data/typed_data.dart patches: @@ -252,25 +271,73 @@ wasm_standalone: _boxed_int: uri: _internal/wasm/lib/boxed_int.dart patches: - _internal/wasm/lib/boxed_int_to_string.dart + _internal/wasm/lib/boxed_int_patch.dart # TODO(53884): Rewrite without JS interop in _internal/wasm_standalone + _boxed_double: + uri: _internal/wasm/lib/boxed_double.dart + patches: + - _internal/wasm/lib/boxed_double_patch.dart # TODO(53884): Rewrite without JS interop in _internal/wasm_standalone _string: - uri: _internal/wasm/lib/js_string.dart + uri: _internal/wasm/lib/js_string.dart # TODO(53884): Rewrite without JS interop in _internal/wasm_standalone _typed_data: uri: _internal/wasm/lib/typed_data.dart - _js_helper: + patches: + - _internal/wasm/lib/typed_data_copy_from_js.dart # TODO(53884): Rewrite without JS interop in _internal/wasm_standalone + _js_helper: # TODO(53884): Remove once other wasm_standalone patches no longer reference this uri: _internal/wasm/lib/js_helper.dart patches: - _internal/wasm/lib/js_helper_patch.dart + _internal: + uri: internal/internal.dart + patches: + - _internal/wasm/lib/internal_patch.dart + - _internal/wasm/lib/deferred_patch.dart # TODO(53884): Rewrite without JS interop in _internal/wasm_standalone + - _internal/wasm/lib/dynamic_module_patch.dart # TODO(53884): Rewrite without JS interop in _internal/wasm_standalone + - _internal/wasm/lib/internal_json_encode_patch.dart # Needs to be migrated + - _internal/wasm/lib/invoke_main_patch.dart # TODO(53884): Rewrite without JS interop in _internal/wasm_standalone + - _internal/wasm/lib/print_patch.dart # TODO(53884): Rewrite without JS interop in _internal/wasm_standalone + _wasm: + uri: _wasm/wasm_types.dart + patches: _internal/wasm/lib/wasm_types_patch.dart # TODO(53884): Remove once other wasm_standalone patches no longer reference this + math: + uri: math/math.dart + patches: + - _internal/wasm/lib/math_patch.dart + - _internal/wasm/lib/math_externs_patch.dart # TODO(53884): Rewrite without JS interop in _internal/wasm_standalone wasm_js_common: include: - target: "wasm_common" libraries: + _boxed_double: + uri: _internal/wasm/lib/boxed_double.dart + patches: + - _internal/wasm/lib/boxed_double_patch.dart + _internal: + uri: internal/internal.dart + patches: + - _internal/wasm/lib/internal_patch.dart + - _internal/wasm/lib/deferred_patch.dart + - _internal/wasm/lib/dynamic_module_patch.dart + - _internal/wasm/lib/internal_json_encode_patch.dart + - _internal/wasm/lib/invoke_main_patch.dart + - _internal/wasm/lib/print_patch.dart + _wasm: + uri: _wasm/wasm_types.dart + patches: _internal/wasm/lib/wasm_types_patch.dart async: uri: async/async.dart patches: - _internal/wasm/lib/async_patch.dart - _internal/wasm/lib/timer_patch.dart + developer: + uri: developer/developer.dart + patches: + - _internal/js_runtime/lib/developer_patch.dart + math: + uri: math/math.dart + patches: + - _internal/wasm/lib/math_patch.dart + - _internal/wasm/lib/math_externs_patch.dart wasm_common: libraries: @@ -282,8 +349,6 @@ wasm_common: uri: _internal/wasm/lib/boxed_bool.dart _boxed_int: uri: _internal/wasm/lib/boxed_int.dart - _boxed_double: - uri: _internal/wasm/lib/boxed_double.dart _compact_hash: uri: _internal/wasm/lib/compact_hash.dart _error_utils: @@ -292,10 +357,6 @@ wasm_common: uri: _http/http.dart patches: - _internal/js_shared/lib/http_patch.dart - _internal: - uri: internal/internal.dart - patches: - - _internal/wasm/lib/internal_patch.dart _js_string_convert: uri: _internal/wasm/lib/js_string_convert.dart _js_types: @@ -308,18 +369,11 @@ wasm_common: uri: _internal/wasm/lib/simd.dart _string_helper: uri: _internal/wasm/lib/string_helper.dart - _wasm: - uri: _wasm/wasm_types.dart - patches: _internal/wasm/lib/wasm_types_patch.dart collection: uri: collection/collection.dart patches: - _internal/vm_shared/lib/collection_patch.dart - _internal/wasm/lib/hash_factories.dart - developer: - uri: developer/developer.dart - patches: - - _internal/js_runtime/lib/developer_patch.dart ffi: uri: "ffi/ffi.dart" patches: @@ -345,9 +399,6 @@ wasm_common: js_interop_unsafe: uri: js_interop_unsafe/js_interop_unsafe.dart patches: _internal/wasm/lib/js_interop_unsafe_patch.dart - math: - uri: math/math.dart - patches: _internal/wasm/lib/math_patch.dart dart2js: include: diff --git a/tests/web/wasm/source_map_simple_test.dart b/tests/web/wasm/source_map_simple_test.dart index 3636a7007c4..d7231f790dc 100644 --- a/tests/web/wasm/source_map_simple_test.dart +++ b/tests/web/wasm/source_map_simple_test.dart @@ -16,18 +16,18 @@ const List<(String?, int?, int?, String?)?> frameDetails = [ ('source_map_simple_lib.dart', 14, 3, 'f'), ('source_map_simple_lib.dart', 43, 5, 'testMain'), ('source_map_simple_test.dart', 10, 7, 'main'), - ('internal_patch.dart', 126, 13, '_invokeMainArg0'), + ('invoke_main_patch.dart', 12, 13, '_invokeMainArg0'), null, - ('internal_patch.dart', 160, 5, '_invokeMain'), + ('invoke_main_patch.dart', 46, 5, '_invokeMain'), ]; /* - at module0.Error._throwWithCurrentStackTrace (wasm://wasm/module0-00110126:wasm-function[108]:0xfd1c) - at module0.g (wasm://wasm/module0-00110126:wasm-function[254]:0x11a8e) - at module0.f (wasm://wasm/module0-00110126:wasm-function[251]:0x11a64) - at module0.testMain (wasm://wasm/module0-00110126:wasm-function[249]:0x115d0) - at module0.main (wasm://wasm/module0-00110126:wasm-function[248]:0x1154b) - at module0._invokeMainArg0 (wasm://wasm/module0-00110126:wasm-function[247]:0x11541) - at module0._invokeMainInternal (wasm://wasm/module0-00110126:wasm-function[82]:0xf8b2) - at module0._invokeMain (wasm://wasm/module0-00110126:wasm-function[77]:0xf815) + at module0.Error._throwWithCurrentStackTrace (wasm://wasm/module0-0010c51a:wasm-function[106]:0xf8c1) + at module0.g (wasm://wasm/module0-0010c51a:wasm-function[254]:0x11767) + at module0.f (wasm://wasm/module0-0010c51a:wasm-function[251]:0x1173d) + at module0.testMain (wasm://wasm/module0-0010c51a:wasm-function[249]:0x112aa) + at module0.main (wasm://wasm/module0-0010c51a:wasm-function[248]:0x11226) + at module0._invokeMainArg0 (wasm://wasm/module0-0010c51a:wasm-function[247]:0x1121c) + at module0._invokeMainInternal (wasm://wasm/module0-0010c51a:wasm-function[81]:0xf50f) + at module0._invokeMain (wasm://wasm/module0-0010c51a:wasm-function[76]:0xf476) */