[dart2wasm] Check types of JS references when boxing JSValues as non-interop types
To make sure Dart values with typed data types like `Uint8List`, `List`, `String` etc. hold the right type of JS values, check types of JS references in boxing functions that return Dart typed data types. To reflect what the functions actually do, and for consistency with other functions, boxing factory names are changed from `fromJSArray` to `fromRef`. New boxing functions `fromRefUnchecked` added for the call sites that already know the reference type to be the right type, for example in `dartifyRaw`. These unchecked functions will also be used in CL 424021 where we replace some `dartifyRaw` calls with more precise "dartify" functions that only converts when the type is right. (`dartifyRaw` always boxes the argument regardless of the type) Issue: https://github.com/dart-lang/sdk/issues/60357 Change-Id: Icdfb49b9b235d35af2af0c4be51b295ee68d99fc Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/429362 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Ömer Ağacan <omersa@google.com>
This commit is contained in:
committed by
Commit Queue
parent
a2312f4776
commit
0246c485e0
@@ -353,7 +353,7 @@ final class BoxedDouble implements double {
|
||||
return "Infinity";
|
||||
}
|
||||
|
||||
String result = JSStringImpl(
|
||||
String result = JSStringImpl.fromRefUnchecked(
|
||||
JS<WasmExternRef?>(
|
||||
'Function.prototype.call.bind(Number.prototype.toString)',
|
||||
WasmF64.fromDouble(value),
|
||||
@@ -400,7 +400,7 @@ final class BoxedDouble implements double {
|
||||
return result;
|
||||
}
|
||||
|
||||
String _toStringAsFixed(int fractionDigits) => JSStringImpl(
|
||||
String _toStringAsFixed(int fractionDigits) => JSStringImpl.fromRefUnchecked(
|
||||
JS<WasmExternRef>(
|
||||
"(d, digits) => d.toFixed(digits)",
|
||||
value,
|
||||
@@ -434,15 +434,16 @@ final class BoxedDouble implements double {
|
||||
return result;
|
||||
}
|
||||
|
||||
String _toStringAsExponential(int? fractionDigits) => JSStringImpl(
|
||||
fractionDigits == null
|
||||
? JS<WasmExternRef>("d => d.toExponential()", value)
|
||||
: JS<WasmExternRef>(
|
||||
"(d, f) => d.toExponential(f)",
|
||||
value,
|
||||
fractionDigits.toDouble(),
|
||||
),
|
||||
);
|
||||
String _toStringAsExponential(int? fractionDigits) =>
|
||||
JSStringImpl.fromRefUnchecked(
|
||||
fractionDigits == null
|
||||
? JS<WasmExternRef>("d => d.toExponential()", value)
|
||||
: JS<WasmExternRef>(
|
||||
"(d, f) => d.toExponential(f)",
|
||||
value,
|
||||
fractionDigits.toDouble(),
|
||||
),
|
||||
);
|
||||
|
||||
String toStringAsPrecision(int precision) {
|
||||
// See ECMAScript-262, 15.7.4.7 for details.
|
||||
@@ -463,13 +464,14 @@ final class BoxedDouble implements double {
|
||||
return result;
|
||||
}
|
||||
|
||||
String _toStringAsPrecision(int fractionDigits) => JSStringImpl(
|
||||
JS<WasmExternRef>(
|
||||
"(d, precision) => d.toPrecision(precision)",
|
||||
value,
|
||||
fractionDigits.toDouble(),
|
||||
),
|
||||
);
|
||||
String _toStringAsPrecision(int fractionDigits) =>
|
||||
JSStringImpl.fromRefUnchecked(
|
||||
JS<WasmExternRef>(
|
||||
"(d, precision) => d.toPrecision(precision)",
|
||||
value,
|
||||
fractionDigits.toDouble(),
|
||||
),
|
||||
);
|
||||
|
||||
// Order is: NaN > Infinity > ... > 0.0 > -0.0 > ... > -Infinity.
|
||||
int compareTo(num other) {
|
||||
|
||||
@@ -35,5 +35,5 @@ String _jsBigIntToString(int i, int radix) {
|
||||
WasmI64.fromInt(i),
|
||||
WasmI32.fromInt(radix),
|
||||
);
|
||||
return JSStringImpl(result);
|
||||
return JSStringImpl.fromRefUnchecked(result);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ class DateTime {
|
||||
|
||||
@patch
|
||||
static String _timeZoneNameForClampedSeconds(int secondsSinceEpoch) =>
|
||||
JSStringImpl(
|
||||
JSStringImpl.fromRefUnchecked(
|
||||
JS<WasmExternRef>(r"""secondsSinceEpoch => {
|
||||
const date = new Date(secondsSinceEpoch * 1000);
|
||||
const match = /\((.*)\)/.exec(date.toString());
|
||||
|
||||
@@ -155,12 +155,14 @@ void _invokeMain(WasmExternRef jsArrayRef) {
|
||||
}
|
||||
}
|
||||
|
||||
String jsonEncode(String object) => JSStringImpl(
|
||||
JS<WasmExternRef>(
|
||||
"s => JSON.stringify(s)",
|
||||
jsStringFromDartString(object).toExternRef,
|
||||
),
|
||||
);
|
||||
String jsonEncode(String object) =>
|
||||
// Use checked boxing as `JSON.stringify` can be patched by users.
|
||||
JSStringImpl.fromRef(
|
||||
JS<WasmExternRef>(
|
||||
"s => JSON.stringify(s)",
|
||||
jsStringFromDartString(object).toExternRef,
|
||||
),
|
||||
);
|
||||
|
||||
/// Whether to check bounds in [IndexErrorUtils.checkIndex],
|
||||
/// which are used in list and typed data implementations.
|
||||
|
||||
@@ -14,13 +14,27 @@ extension JSArrayImplUncheckedOperations<T extends JSAny?> on JSArrayImpl {
|
||||
class JSArrayImpl<T extends JSAny?> implements List<T> {
|
||||
final WasmExternRef? _ref;
|
||||
|
||||
JSArrayImpl(this._ref);
|
||||
static bool _checkRefType(WasmExternRef? ref) =>
|
||||
js.JS<bool>('o => o instanceof Array', ref);
|
||||
|
||||
JSArrayImpl.fromRefUnchecked(this._ref) {
|
||||
assert(_checkRefType(_ref));
|
||||
}
|
||||
|
||||
factory JSArrayImpl.fromRef(WasmExternRef? ref) {
|
||||
if (!_checkRefType(ref)) {
|
||||
throw minify
|
||||
? ArgumentError()
|
||||
: ArgumentError("JS reference is not an array");
|
||||
}
|
||||
return JSArrayImpl<T>.fromRefUnchecked(ref);
|
||||
}
|
||||
|
||||
factory JSArrayImpl.fromLength(int length) =>
|
||||
JSArrayImpl<T>(js.newArrayFromLengthRaw(length));
|
||||
JSArrayImpl<T>.fromRefUnchecked(js.newArrayFromLengthRaw(length));
|
||||
|
||||
static JSArrayImpl<T>? box<T extends JSAny?>(WasmExternRef? ref) =>
|
||||
js.isDartNull(ref) ? null : JSArrayImpl<T>(ref);
|
||||
js.isDartNull(ref) ? null : JSArrayImpl<T>.fromRefUnchecked(ref);
|
||||
|
||||
WasmExternRef? get toExternRef => _ref;
|
||||
|
||||
@@ -165,7 +179,7 @@ class JSArrayImpl<T extends JSAny?> implements List<T> {
|
||||
toExternRef,
|
||||
separator.toExternRef,
|
||||
);
|
||||
return JSStringImpl(result);
|
||||
return JSStringImpl.fromRefUnchecked(result);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -257,7 +271,7 @@ class JSArrayImpl<T extends JSAny?> implements List<T> {
|
||||
@override
|
||||
List<T> sublist(int start, [int? end]) {
|
||||
end = RangeErrorUtils.checkValidRange(start, end, length);
|
||||
return JSArrayImpl<T>(
|
||||
return JSArrayImpl<T>.fromRefUnchecked(
|
||||
js.JS<WasmExternRef?>(
|
||||
'(a, s, e) => a.slice(s, e)',
|
||||
toExternRef,
|
||||
@@ -538,7 +552,7 @@ class JSArrayImpl<T extends JSAny?> implements List<T> {
|
||||
@override
|
||||
List<T> operator +(List<T> other) {
|
||||
if (other is JSArrayImpl) {
|
||||
return JSArrayImpl<T>(
|
||||
return JSArrayImpl<T>.fromRefUnchecked(
|
||||
js.JS<WasmExternRef?>(
|
||||
'(a, t) => a.concat(t)',
|
||||
toExternRef,
|
||||
|
||||
@@ -259,10 +259,10 @@ WasmExternRef? callMethodVarArgsRaw(
|
||||
) => JS<WasmExternRef?>("(o, m, a) => o[m].apply(o, a)", o, method, args);
|
||||
|
||||
String typeof(WasmExternRef? object) =>
|
||||
JSStringImpl(JS<WasmExternRef?>("o => typeof o", object));
|
||||
JSStringImpl.fromRefUnchecked(JS<WasmExternRef?>("o => typeof o", object));
|
||||
|
||||
String stringify(WasmExternRef? object) =>
|
||||
JSStringImpl(JS<WasmExternRef?>("o => String(o)", object));
|
||||
JSStringImpl.fromRefUnchecked(JS<WasmExternRef?>("o => String(o)", object));
|
||||
|
||||
void promiseThen(
|
||||
WasmExternRef? promise,
|
||||
@@ -491,20 +491,30 @@ Object? dartifyRaw(WasmExternRef? ref, [int? refType]) {
|
||||
ExternRefType.null_ || ExternRefType.undefined => null,
|
||||
ExternRefType.boolean => toDartBool(ref),
|
||||
ExternRefType.number => toDartNumber(ref),
|
||||
ExternRefType.string => JSStringImpl.box(ref),
|
||||
ExternRefType.string => JSStringImpl.fromRefUnchecked(ref),
|
||||
ExternRefType.array => toDartList(ref),
|
||||
ExternRefType.int8Array => js_types.JSInt8ArrayImpl.fromJSArray(ref),
|
||||
ExternRefType.uint8Array => js_types.JSUint8ArrayImpl.fromJSArray(ref),
|
||||
ExternRefType.int8Array => js_types.JSInt8ArrayImpl.fromRefUnchecked(ref),
|
||||
ExternRefType.uint8Array => js_types.JSUint8ArrayImpl.fromRefUnchecked(ref),
|
||||
ExternRefType.uint8ClampedArray =>
|
||||
js_types.JSUint8ClampedArrayImpl.fromJSArray(ref),
|
||||
ExternRefType.int16Array => js_types.JSInt16ArrayImpl.fromJSArray(ref),
|
||||
ExternRefType.uint16Array => js_types.JSUint16ArrayImpl.fromJSArray(ref),
|
||||
ExternRefType.int32Array => js_types.JSInt32ArrayImpl.fromJSArray(ref),
|
||||
ExternRefType.uint32Array => js_types.JSUint32ArrayImpl.fromJSArray(ref),
|
||||
ExternRefType.float32Array => js_types.JSFloat32ArrayImpl.fromJSArray(ref),
|
||||
ExternRefType.float64Array => js_types.JSFloat64ArrayImpl.fromJSArray(ref),
|
||||
ExternRefType.arrayBuffer => js_types.JSArrayBufferImpl.fromRef(ref),
|
||||
ExternRefType.dataView => js_types.JSDataViewImpl.fromRef(ref),
|
||||
js_types.JSUint8ClampedArrayImpl.fromRefUnchecked(ref),
|
||||
ExternRefType.int16Array => js_types.JSInt16ArrayImpl.fromRefUnchecked(ref),
|
||||
ExternRefType.uint16Array => js_types.JSUint16ArrayImpl.fromRefUnchecked(
|
||||
ref,
|
||||
),
|
||||
ExternRefType.int32Array => js_types.JSInt32ArrayImpl.fromRefUnchecked(ref),
|
||||
ExternRefType.uint32Array => js_types.JSUint32ArrayImpl.fromRefUnchecked(
|
||||
ref,
|
||||
),
|
||||
ExternRefType.float32Array => js_types.JSFloat32ArrayImpl.fromRefUnchecked(
|
||||
ref,
|
||||
),
|
||||
ExternRefType.float64Array => js_types.JSFloat64ArrayImpl.fromRefUnchecked(
|
||||
ref,
|
||||
),
|
||||
ExternRefType.arrayBuffer => js_types.JSArrayBufferImpl.fromRefUnchecked(
|
||||
ref,
|
||||
),
|
||||
ExternRefType.dataView => js_types.JSDataViewImpl.fromRefUnchecked(ref),
|
||||
ExternRefType.unknown =>
|
||||
isJSWrappedDartFunction(ref)
|
||||
? unwrapJSWrappedDartFunction(ref)
|
||||
|
||||
@@ -279,7 +279,7 @@ extension ByteDataToJSDataView on ByteData {
|
||||
@patch
|
||||
extension JSInt8ArrayToInt8List on JSInt8Array {
|
||||
@patch
|
||||
Int8List get toDart => js_types.JSInt8ArrayImpl.fromJSArray(toExternRef);
|
||||
Int8List get toDart => js_types.JSInt8ArrayImpl.fromRef(toExternRef);
|
||||
}
|
||||
|
||||
@patch
|
||||
@@ -302,7 +302,7 @@ extension Int8ListToJSInt8Array on Int8List {
|
||||
@patch
|
||||
extension JSUint8ArrayToUint8List on JSUint8Array {
|
||||
@patch
|
||||
Uint8List get toDart => js_types.JSUint8ArrayImpl.fromJSArray(toExternRef);
|
||||
Uint8List get toDart => js_types.JSUint8ArrayImpl.fromRef(toExternRef);
|
||||
}
|
||||
|
||||
@patch
|
||||
@@ -326,7 +326,7 @@ extension Uint8ListToJSUint8Array on Uint8List {
|
||||
extension JSUint8ClampedArrayToUint8ClampedList on JSUint8ClampedArray {
|
||||
@patch
|
||||
Uint8ClampedList get toDart =>
|
||||
js_types.JSUint8ClampedArrayImpl.fromJSArray(toExternRef);
|
||||
js_types.JSUint8ClampedArrayImpl.fromRef(toExternRef);
|
||||
}
|
||||
|
||||
@patch
|
||||
@@ -349,7 +349,7 @@ extension Uint8ClampedListToJSUint8ClampedArray on Uint8ClampedList {
|
||||
@patch
|
||||
extension JSInt16ArrayToInt16List on JSInt16Array {
|
||||
@patch
|
||||
Int16List get toDart => js_types.JSInt16ArrayImpl.fromJSArray(toExternRef);
|
||||
Int16List get toDart => js_types.JSInt16ArrayImpl.fromRef(toExternRef);
|
||||
}
|
||||
|
||||
@patch
|
||||
@@ -372,7 +372,7 @@ extension Int16ListToJSInt16Array on Int16List {
|
||||
@patch
|
||||
extension JSUint16ArrayToInt16List on JSUint16Array {
|
||||
@patch
|
||||
Uint16List get toDart => js_types.JSUint16ArrayImpl.fromJSArray(toExternRef);
|
||||
Uint16List get toDart => js_types.JSUint16ArrayImpl.fromRef(toExternRef);
|
||||
}
|
||||
|
||||
@patch
|
||||
@@ -395,7 +395,7 @@ extension Uint16ListToJSInt16Array on Uint16List {
|
||||
@patch
|
||||
extension JSInt32ArrayToInt32List on JSInt32Array {
|
||||
@patch
|
||||
Int32List get toDart => js_types.JSInt32ArrayImpl.fromJSArray(toExternRef);
|
||||
Int32List get toDart => js_types.JSInt32ArrayImpl.fromRef(toExternRef);
|
||||
}
|
||||
|
||||
@patch
|
||||
@@ -418,7 +418,7 @@ extension Int32ListToJSInt32Array on Int32List {
|
||||
@patch
|
||||
extension JSUint32ArrayToUint32List on JSUint32Array {
|
||||
@patch
|
||||
Uint32List get toDart => js_types.JSUint32ArrayImpl.fromJSArray(toExternRef);
|
||||
Uint32List get toDart => js_types.JSUint32ArrayImpl.fromRef(toExternRef);
|
||||
}
|
||||
|
||||
@patch
|
||||
@@ -441,8 +441,7 @@ extension Uint32ListToJSUint32Array on Uint32List {
|
||||
@patch
|
||||
extension JSFloat32ArrayToFloat32List on JSFloat32Array {
|
||||
@patch
|
||||
Float32List get toDart =>
|
||||
js_types.JSFloat32ArrayImpl.fromJSArray(toExternRef);
|
||||
Float32List get toDart => js_types.JSFloat32ArrayImpl.fromRef(toExternRef);
|
||||
}
|
||||
|
||||
@patch
|
||||
@@ -465,8 +464,7 @@ extension Float32ListToJSFloat32Array on Float32List {
|
||||
@patch
|
||||
extension JSFloat64ArrayToFloat64List on JSFloat64Array {
|
||||
@patch
|
||||
Float64List get toDart =>
|
||||
js_types.JSFloat64ArrayImpl.fromJSArray(toExternRef);
|
||||
Float64List get toDart => js_types.JSFloat64ArrayImpl.fromRef(toExternRef);
|
||||
}
|
||||
|
||||
@patch
|
||||
@@ -489,7 +487,7 @@ extension Float64ListToJSFloat64Array on Float64List {
|
||||
@patch
|
||||
extension JSArrayToList<T extends JSAny?> on JSArray<T> {
|
||||
@patch
|
||||
List<T> get toDart => js_types.JSArrayImpl<T>(toExternRef);
|
||||
List<T> get toDart => js_types.JSArrayImpl<T>.fromRef(toExternRef);
|
||||
}
|
||||
|
||||
@patch
|
||||
@@ -554,7 +552,7 @@ extension BoolToJSBoolean on bool {
|
||||
@patch
|
||||
extension JSStringToString on JSString {
|
||||
@patch
|
||||
String get toDart => JSStringImpl(toExternRef);
|
||||
String get toDart => JSStringImpl.fromRef(toExternRef);
|
||||
}
|
||||
|
||||
@patch
|
||||
|
||||
@@ -34,11 +34,24 @@ extension StringUncheckedOperations on String {
|
||||
final class JSStringImpl implements String, StringUncheckedOperationsBase {
|
||||
final WasmExternRef? _ref;
|
||||
|
||||
JSStringImpl(this._ref);
|
||||
static bool _checkRefType(WasmExternRef? ref) => jsStringTest(ref).toBool();
|
||||
|
||||
JSStringImpl.fromRefUnchecked(this._ref) {
|
||||
assert(_checkRefType(_ref));
|
||||
}
|
||||
|
||||
factory JSStringImpl.fromRef(WasmExternRef? ref) {
|
||||
if (!_checkRefType(ref)) {
|
||||
throw minify
|
||||
? ArgumentError()
|
||||
: ArgumentError("JS reference is not a string");
|
||||
}
|
||||
return JSStringImpl.fromRefUnchecked(ref);
|
||||
}
|
||||
|
||||
@pragma("wasm:prefer-inline")
|
||||
static String? box(WasmExternRef? ref) =>
|
||||
js.isDartNull(ref) ? null : JSStringImpl(ref);
|
||||
js.isDartNull(ref) ? null : JSStringImpl.fromRefUnchecked(ref);
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
@@ -71,7 +84,7 @@ final class JSStringImpl implements String, StringUncheckedOperationsBase {
|
||||
static String _interpolate2(Object? value1, Object? value2) {
|
||||
final String string1 = value1 is String ? value1 : value1.toString();
|
||||
final String string2 = value2 is String ? value2 : value2.toString();
|
||||
return JSStringImpl(
|
||||
return JSStringImpl.fromRefUnchecked(
|
||||
_jsStringConcatImport(
|
||||
unsafeCast<JSStringImpl>(string1).toExternRef,
|
||||
unsafeCast<JSStringImpl>(string2).toExternRef,
|
||||
@@ -84,7 +97,7 @@ final class JSStringImpl implements String, StringUncheckedOperationsBase {
|
||||
final String string1 = value1 is String ? value1 : value1.toString();
|
||||
final String string2 = value2 is String ? value2 : value2.toString();
|
||||
final String string3 = value3 is String ? value3 : value3.toString();
|
||||
return JSStringImpl(
|
||||
return JSStringImpl.fromRefUnchecked(
|
||||
_jsStringConcatImport(
|
||||
_jsStringConcatImport(
|
||||
unsafeCast<JSStringImpl>(string1).toExternRef,
|
||||
@@ -106,7 +119,7 @@ final class JSStringImpl implements String, StringUncheckedOperationsBase {
|
||||
final String string2 = value2 is String ? value2 : value2.toString();
|
||||
final String string3 = value3 is String ? value3 : value3.toString();
|
||||
final String string4 = value4 is String ? value4 : value4.toString();
|
||||
return JSStringImpl(
|
||||
return JSStringImpl.fromRefUnchecked(
|
||||
_jsStringConcatImport(
|
||||
_jsStringConcatImport(
|
||||
unsafeCast<JSStringImpl>(string1).toExternRef,
|
||||
@@ -148,7 +161,7 @@ final class JSStringImpl implements String, StringUncheckedOperationsBase {
|
||||
int start,
|
||||
int end,
|
||||
) {
|
||||
return JSStringImpl(
|
||||
return JSStringImpl.fromRefUnchecked(
|
||||
jsStringFromCharCodeArray(source, start.toWasmI32(), end.toWasmI32()),
|
||||
);
|
||||
}
|
||||
@@ -214,7 +227,7 @@ final class JSStringImpl implements String, StringUncheckedOperationsBase {
|
||||
@override
|
||||
@pragma('dyn-module:callable')
|
||||
String operator +(String other) {
|
||||
return JSStringImpl(
|
||||
return JSStringImpl.fromRefUnchecked(
|
||||
_jsStringConcatImport(
|
||||
toExternRef,
|
||||
unsafeCast<JSStringImpl>(other).toExternRef,
|
||||
@@ -464,7 +477,7 @@ final class JSStringImpl implements String, StringUncheckedOperationsBase {
|
||||
@override
|
||||
@pragma('wasm:prefer-inline')
|
||||
String _substringUnchecked(int start, int end) =>
|
||||
JSStringImpl(_jsSubstring(toExternRef, start, end));
|
||||
JSStringImpl.fromRefUnchecked(_jsSubstring(toExternRef, start, end));
|
||||
|
||||
@override
|
||||
String toLowerCase() {
|
||||
@@ -472,7 +485,7 @@ final class JSStringImpl implements String, StringUncheckedOperationsBase {
|
||||
final lowerCaseRef = _jsStringToLowerCase(thisRef);
|
||||
return _jsIdentical(thisRef, lowerCaseRef)
|
||||
? this
|
||||
: JSStringImpl(lowerCaseRef);
|
||||
: JSStringImpl.fromRefUnchecked(lowerCaseRef);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -481,7 +494,7 @@ final class JSStringImpl implements String, StringUncheckedOperationsBase {
|
||||
final upperCaseRef = _jsStringToUpperCase(thisRef);
|
||||
return _jsIdentical(thisRef, upperCaseRef)
|
||||
? this
|
||||
: JSStringImpl(upperCaseRef);
|
||||
: JSStringImpl.fromRefUnchecked(upperCaseRef);
|
||||
}
|
||||
|
||||
// Characters with Whitespace property (Unicode 6.3).
|
||||
@@ -585,7 +598,7 @@ final class JSStringImpl implements String, StringUncheckedOperationsBase {
|
||||
|
||||
// Start by doing JS trim. Then check if it leaves a NEL at either end of
|
||||
// the string.
|
||||
final result = JSStringImpl(_jsStringTrim(toExternRef));
|
||||
final result = JSStringImpl.fromRefUnchecked(_jsStringTrim(toExternRef));
|
||||
final resultLength = result.length;
|
||||
if (resultLength == 0) return result;
|
||||
|
||||
@@ -623,7 +636,9 @@ final class JSStringImpl implements String, StringUncheckedOperationsBase {
|
||||
// Start by doing JS trim. Then check if it leaves a NEL at the beginning
|
||||
// of the string.
|
||||
int startIndex = 0;
|
||||
final result = JSStringImpl(_jsStringTrimLeft(toExternRef));
|
||||
final result = JSStringImpl.fromRefUnchecked(
|
||||
_jsStringTrimLeft(toExternRef),
|
||||
);
|
||||
final resultLength = result.length;
|
||||
if (resultLength == 0) return result;
|
||||
|
||||
@@ -649,7 +664,9 @@ final class JSStringImpl implements String, StringUncheckedOperationsBase {
|
||||
|
||||
// Start by doing JS trim. Then check if it leaves a NEL at the end of the
|
||||
// string.
|
||||
final result = JSStringImpl(_jsStringTrimRight(toExternRef));
|
||||
final result = JSStringImpl.fromRefUnchecked(
|
||||
_jsStringTrimRight(toExternRef),
|
||||
);
|
||||
final resultLength = result.length;
|
||||
if (resultLength == 0) return result;
|
||||
|
||||
@@ -675,7 +692,7 @@ final class JSStringImpl implements String, StringUncheckedOperationsBase {
|
||||
'The implementation cannot handle very large operands (was: $times).',
|
||||
);
|
||||
}
|
||||
return JSStringImpl(_jsStringRepeat(toExternRef, times));
|
||||
return JSStringImpl.fromRefUnchecked(_jsStringRepeat(toExternRef, times));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -831,7 +848,7 @@ JSStringImpl _jsStringReplaceAll(
|
||||
WasmExternRef? string,
|
||||
WasmExternRef? pattern,
|
||||
WasmExternRef? replacement,
|
||||
) => JSStringImpl(
|
||||
) => JSStringImpl.fromRefUnchecked(
|
||||
js.JS<WasmExternRef?>(
|
||||
'(o, p, r) => o.replaceAll(p, () => r)',
|
||||
string,
|
||||
@@ -846,7 +863,7 @@ String _jsStringReplace(
|
||||
WasmExternRef? string,
|
||||
WasmExternRef? pattern,
|
||||
WasmExternRef? replacement,
|
||||
) => JSStringImpl(
|
||||
) => JSStringImpl.fromRefUnchecked(
|
||||
js.JS<WasmExternRef?>(
|
||||
'(o, p, r) => o.replace(p, () => r)',
|
||||
string,
|
||||
@@ -1008,3 +1025,6 @@ external WasmI32 jsStringIntoCharCodeArray(
|
||||
WasmArray<WasmI16>? array,
|
||||
WasmI32 start,
|
||||
);
|
||||
|
||||
@pragma("wasm:import", "wasm:js-string.test")
|
||||
external WasmI32 jsStringTest(WasmExternRef? s);
|
||||
|
||||
@@ -36,7 +36,7 @@ JSStringImpl? _useTextDecoder(
|
||||
// back on unintercepted decoder. The fallback will either succeed in
|
||||
// decoding, or report the problem better than `TextDecoder`.
|
||||
try {
|
||||
return JSStringImpl(
|
||||
return JSStringImpl.fromRefUnchecked(
|
||||
js.JS<WasmExternRef?>(
|
||||
'(decoder, codeUnits) => decoder.decode(codeUnits)',
|
||||
decoder,
|
||||
|
||||
@@ -11,9 +11,21 @@ final class JSArrayBufferImpl implements ByteBuffer {
|
||||
|
||||
final bool _immutable;
|
||||
|
||||
JSArrayBufferImpl.fromRef(this._ref) : _immutable = false;
|
||||
static bool _checkRefType(WasmExternRef? ref) =>
|
||||
js.JS<bool>('o => o instanceof ArrayBuffer', ref);
|
||||
|
||||
JSArrayBufferImpl.fromRefImmutable(this._ref) : _immutable = true;
|
||||
JSArrayBufferImpl.fromRefUnchecked(this._ref) : _immutable = false {
|
||||
assert(_checkRefType(_ref));
|
||||
}
|
||||
|
||||
JSArrayBufferImpl.fromRefImmutableUnchecked(this._ref) : _immutable = true;
|
||||
|
||||
factory JSArrayBufferImpl.fromRef(WasmExternRef? ref) {
|
||||
if (!_checkRefType(ref)) {
|
||||
return _throwConversionFailureError("ByteBuffer");
|
||||
}
|
||||
return JSArrayBufferImpl.fromRefUnchecked(ref);
|
||||
}
|
||||
|
||||
@pragma("wasm:prefer-inline")
|
||||
WasmExternRef? get toExternRef => _ref;
|
||||
@@ -168,7 +180,7 @@ abstract class JSArrayBase implements TypedData {
|
||||
|
||||
@override
|
||||
JSArrayBufferImpl get buffer =>
|
||||
JSArrayBufferImpl.fromRef(_dataViewBuffer(_ref));
|
||||
JSArrayBufferImpl.fromRefUnchecked(_dataViewBuffer(_ref));
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
@@ -238,21 +250,35 @@ final class JSDataViewImpl implements ByteData {
|
||||
|
||||
final bool _immutable;
|
||||
|
||||
static bool _checkRefType(WasmExternRef? ref) =>
|
||||
js.JS<bool>('o => o instanceof DataView', ref);
|
||||
|
||||
JSDataViewImpl._(this._ref, this.lengthInBytes, this._immutable) {
|
||||
assert(_checkRefType(_ref));
|
||||
}
|
||||
|
||||
JSDataViewImpl(this.lengthInBytes)
|
||||
: _ref = _newDataView(lengthInBytes),
|
||||
_immutable = false;
|
||||
|
||||
JSDataViewImpl.fromRef(this._ref)
|
||||
JSDataViewImpl.fromRefUnchecked(this._ref)
|
||||
: lengthInBytes = _dataViewByteLength(_ref),
|
||||
_immutable = false;
|
||||
|
||||
factory JSDataViewImpl.fromRef(WasmExternRef? ref) {
|
||||
if (!_checkRefType(ref)) {
|
||||
return _throwConversionFailureError("ByteData");
|
||||
}
|
||||
return JSDataViewImpl.fromRefUnchecked(ref);
|
||||
}
|
||||
|
||||
JSDataViewImpl.immutable(this._ref, this.lengthInBytes) : _immutable = true;
|
||||
|
||||
factory JSDataViewImpl.view(
|
||||
JSArrayBufferImpl buffer,
|
||||
int offsetInBytes,
|
||||
int? length,
|
||||
) => JSDataViewImpl.fromRef(
|
||||
) => JSDataViewImpl.fromRefUnchecked(
|
||||
_newDataViewFromArrayBuffer(buffer.toExternRef, offsetInBytes, length),
|
||||
);
|
||||
|
||||
@@ -261,8 +287,10 @@ final class JSDataViewImpl implements ByteData {
|
||||
|
||||
@override
|
||||
JSArrayBufferImpl get buffer => _immutable
|
||||
? JSArrayBufferImpl.fromRefImmutable(_dataViewBuffer(toExternRef))
|
||||
: JSArrayBufferImpl.fromRef(_dataViewBuffer(toExternRef));
|
||||
? JSArrayBufferImpl.fromRefImmutableUnchecked(
|
||||
_dataViewBuffer(toExternRef),
|
||||
)
|
||||
: JSArrayBufferImpl.fromRefUnchecked(_dataViewBuffer(toExternRef));
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
@@ -732,7 +760,7 @@ mixin _UnmodifiableIntListMixin {
|
||||
WasmExternRef? get toExternRef;
|
||||
|
||||
JSArrayBufferImpl get buffer =>
|
||||
JSArrayBufferImpl.fromRefImmutable(_dataViewBuffer(toExternRef));
|
||||
JSArrayBufferImpl.fromRefImmutableUnchecked(_dataViewBuffer(toExternRef));
|
||||
|
||||
void operator []=(int index, int value) {
|
||||
throw UnsupportedError("Cannot modify an unmodifiable list");
|
||||
@@ -756,8 +784,20 @@ final class JSUint8ArrayImpl extends JSIntegerArrayBase
|
||||
factory JSUint8ArrayImpl(int length) =>
|
||||
JSUint8ArrayImpl._(_newDataView(length));
|
||||
|
||||
factory JSUint8ArrayImpl.fromJSArray(WasmExternRef? jsArrayRef) =>
|
||||
JSUint8ArrayImpl._(_dataViewFromJSArray(jsArrayRef));
|
||||
static bool _checkRefType(WasmExternRef? ref) =>
|
||||
js.JS<bool>('o => o instanceof Uint8Array', ref);
|
||||
|
||||
factory JSUint8ArrayImpl.fromRefUnchecked(WasmExternRef? ref) {
|
||||
_checkRefType(ref);
|
||||
return JSUint8ArrayImpl._(_dataViewFromJSArray(ref));
|
||||
}
|
||||
|
||||
factory JSUint8ArrayImpl.fromRef(WasmExternRef? ref) {
|
||||
if (!_checkRefType(ref)) {
|
||||
return _throwConversionFailureError("Uint8List");
|
||||
}
|
||||
return JSUint8ArrayImpl.fromRefUnchecked(ref);
|
||||
}
|
||||
|
||||
factory JSUint8ArrayImpl.view(
|
||||
JSArrayBufferImpl buffer,
|
||||
@@ -848,8 +888,20 @@ final class JSInt8ArrayImpl extends JSIntegerArrayBase
|
||||
factory JSInt8ArrayImpl(int length) =>
|
||||
JSInt8ArrayImpl._(_newDataView(length));
|
||||
|
||||
factory JSInt8ArrayImpl.fromJSArray(WasmExternRef? jsArrayRef) =>
|
||||
JSInt8ArrayImpl._(_dataViewFromJSArray(jsArrayRef));
|
||||
static bool _checkRefType(WasmExternRef? ref) =>
|
||||
js.JS<bool>('o => o instanceof Int8Array', ref);
|
||||
|
||||
factory JSInt8ArrayImpl.fromRefUnchecked(WasmExternRef? ref) {
|
||||
assert(_checkRefType(ref));
|
||||
return JSInt8ArrayImpl._(_dataViewFromJSArray(ref));
|
||||
}
|
||||
|
||||
factory JSInt8ArrayImpl.fromRef(WasmExternRef? ref) {
|
||||
if (!_checkRefType(ref)) {
|
||||
return _throwConversionFailureError("Int8List");
|
||||
}
|
||||
return JSInt8ArrayImpl.fromRefUnchecked(ref);
|
||||
}
|
||||
|
||||
factory JSInt8ArrayImpl.view(
|
||||
JSArrayBufferImpl buffer,
|
||||
@@ -940,8 +992,20 @@ final class JSUint8ClampedArrayImpl extends JSIntegerArrayBase
|
||||
factory JSUint8ClampedArrayImpl(int length) =>
|
||||
JSUint8ClampedArrayImpl._(_newDataView(length));
|
||||
|
||||
factory JSUint8ClampedArrayImpl.fromJSArray(WasmExternRef? jsArrayRef) =>
|
||||
JSUint8ClampedArrayImpl._(_dataViewFromJSArray(jsArrayRef));
|
||||
static bool _checkRefType(WasmExternRef? ref) =>
|
||||
js.JS<bool>('o => o instanceof Uint8ClampedArray', ref);
|
||||
|
||||
factory JSUint8ClampedArrayImpl.fromRefUnchecked(WasmExternRef? ref) {
|
||||
assert(_checkRefType(ref));
|
||||
return JSUint8ClampedArrayImpl._(_dataViewFromJSArray(ref));
|
||||
}
|
||||
|
||||
factory JSUint8ClampedArrayImpl.fromRef(WasmExternRef? ref) {
|
||||
if (!_checkRefType(ref)) {
|
||||
return _throwConversionFailureError("Uint8ClampedList");
|
||||
}
|
||||
return JSUint8ClampedArrayImpl.fromRefUnchecked(ref);
|
||||
}
|
||||
|
||||
factory JSUint8ClampedArrayImpl.view(
|
||||
JSArrayBufferImpl buffer,
|
||||
@@ -1020,8 +1084,20 @@ final class JSUint16ArrayImpl extends JSIntegerArrayBase
|
||||
factory JSUint16ArrayImpl(int length) =>
|
||||
JSUint16ArrayImpl._(_newDataView(length * 2));
|
||||
|
||||
factory JSUint16ArrayImpl.fromJSArray(WasmExternRef? jsArrayRef) =>
|
||||
JSUint16ArrayImpl._(_dataViewFromJSArray(jsArrayRef));
|
||||
static bool _checkRefType(WasmExternRef? ref) =>
|
||||
js.JS<bool>('o => o instanceof Uint16Array', ref);
|
||||
|
||||
factory JSUint16ArrayImpl.fromRefUnchecked(WasmExternRef? ref) {
|
||||
assert(_checkRefType(ref));
|
||||
return JSUint16ArrayImpl._(_dataViewFromJSArray(ref));
|
||||
}
|
||||
|
||||
factory JSUint16ArrayImpl.fromRef(WasmExternRef? ref) {
|
||||
if (!_checkRefType(ref)) {
|
||||
return _throwConversionFailureError("Uint16List");
|
||||
}
|
||||
return JSUint16ArrayImpl.fromRefUnchecked(ref);
|
||||
}
|
||||
|
||||
factory JSUint16ArrayImpl.view(
|
||||
JSArrayBufferImpl buffer,
|
||||
@@ -1120,8 +1196,20 @@ final class JSInt16ArrayImpl extends JSIntegerArrayBase
|
||||
factory JSInt16ArrayImpl(int length) =>
|
||||
JSInt16ArrayImpl._(_newDataView(length * 2));
|
||||
|
||||
factory JSInt16ArrayImpl.fromJSArray(WasmExternRef? jsArrayRef) =>
|
||||
JSInt16ArrayImpl._(_dataViewFromJSArray(jsArrayRef));
|
||||
static bool _checkRefType(WasmExternRef? ref) =>
|
||||
js.JS<bool>('o => o instanceof Int16Array', ref);
|
||||
|
||||
factory JSInt16ArrayImpl.fromRefUnchecked(WasmExternRef? ref) {
|
||||
assert(_checkRefType(ref));
|
||||
return JSInt16ArrayImpl._(_dataViewFromJSArray(ref));
|
||||
}
|
||||
|
||||
factory JSInt16ArrayImpl.fromRef(WasmExternRef? ref) {
|
||||
if (!_checkRefType(ref)) {
|
||||
return _throwConversionFailureError("Int16List");
|
||||
}
|
||||
return JSInt16ArrayImpl.fromRefUnchecked(ref);
|
||||
}
|
||||
|
||||
factory JSInt16ArrayImpl.view(
|
||||
JSArrayBufferImpl buffer,
|
||||
@@ -1220,8 +1308,20 @@ final class JSUint32ArrayImpl extends JSIntegerArrayBase
|
||||
factory JSUint32ArrayImpl(int length) =>
|
||||
JSUint32ArrayImpl._(_newDataView(length * 4));
|
||||
|
||||
factory JSUint32ArrayImpl.fromJSArray(WasmExternRef? jsArrayRef) =>
|
||||
JSUint32ArrayImpl._(_dataViewFromJSArray(jsArrayRef));
|
||||
static bool _checkRefType(WasmExternRef? ref) =>
|
||||
js.JS<bool>('o => o instanceof Uint32Array', ref);
|
||||
|
||||
factory JSUint32ArrayImpl.fromRefUnchecked(WasmExternRef? ref) {
|
||||
assert(_checkRefType(ref));
|
||||
return JSUint32ArrayImpl._(_dataViewFromJSArray(ref));
|
||||
}
|
||||
|
||||
factory JSUint32ArrayImpl.fromRef(WasmExternRef? ref) {
|
||||
if (!_checkRefType(ref)) {
|
||||
return _throwConversionFailureError("Uint32List");
|
||||
}
|
||||
return JSUint32ArrayImpl.fromRefUnchecked(ref);
|
||||
}
|
||||
|
||||
factory JSUint32ArrayImpl.view(
|
||||
JSArrayBufferImpl buffer,
|
||||
@@ -1320,8 +1420,20 @@ final class JSInt32ArrayImpl extends JSIntegerArrayBase
|
||||
factory JSInt32ArrayImpl(int length) =>
|
||||
JSInt32ArrayImpl._(_newDataView(length * 4));
|
||||
|
||||
factory JSInt32ArrayImpl.fromJSArray(WasmExternRef? jsArrayRef) =>
|
||||
JSInt32ArrayImpl._(_dataViewFromJSArray(jsArrayRef));
|
||||
static bool _checkRefType(WasmExternRef? ref) =>
|
||||
js.JS<bool>('o => o instanceof Int32Array', ref);
|
||||
|
||||
factory JSInt32ArrayImpl.fromRefUnchecked(WasmExternRef? ref) {
|
||||
assert(_checkRefType(ref));
|
||||
return JSInt32ArrayImpl._(_dataViewFromJSArray(ref));
|
||||
}
|
||||
|
||||
factory JSInt32ArrayImpl.fromRef(WasmExternRef? ref) {
|
||||
if (!_checkRefType(ref)) {
|
||||
return _throwConversionFailureError("Int32List");
|
||||
}
|
||||
return JSInt32ArrayImpl.fromRefUnchecked(ref);
|
||||
}
|
||||
|
||||
factory JSInt32ArrayImpl.view(
|
||||
JSArrayBufferImpl buffer,
|
||||
@@ -2031,7 +2143,7 @@ mixin _UnmodifiableDoubleListMixin {
|
||||
WasmExternRef? get toExternRef;
|
||||
|
||||
JSArrayBufferImpl get buffer =>
|
||||
JSArrayBufferImpl.fromRefImmutable(_dataViewBuffer(toExternRef));
|
||||
JSArrayBufferImpl.fromRefImmutableUnchecked(_dataViewBuffer(toExternRef));
|
||||
|
||||
void operator []=(int index, double value) {
|
||||
throw UnsupportedError("Cannot modify an unmodifiable list");
|
||||
@@ -2055,8 +2167,20 @@ final class JSFloat32ArrayImpl extends JSFloatArrayBase
|
||||
factory JSFloat32ArrayImpl(int length) =>
|
||||
JSFloat32ArrayImpl._(_newDataView(length * 4));
|
||||
|
||||
factory JSFloat32ArrayImpl.fromJSArray(WasmExternRef? jsArrayRef) =>
|
||||
JSFloat32ArrayImpl._(_dataViewFromJSArray(jsArrayRef));
|
||||
static bool _checkRefType(WasmExternRef? ref) =>
|
||||
js.JS<bool>('o => o instanceof Float32Array', ref);
|
||||
|
||||
factory JSFloat32ArrayImpl.fromRefUnchecked(WasmExternRef? ref) {
|
||||
assert(_checkRefType(ref));
|
||||
return JSFloat32ArrayImpl._(_dataViewFromJSArray(ref));
|
||||
}
|
||||
|
||||
factory JSFloat32ArrayImpl.fromRef(WasmExternRef? ref) {
|
||||
if (!_checkRefType(ref)) {
|
||||
return _throwConversionFailureError("Float32List");
|
||||
}
|
||||
return JSFloat32ArrayImpl.fromRefUnchecked(ref);
|
||||
}
|
||||
|
||||
factory JSFloat32ArrayImpl.view(
|
||||
JSArrayBufferImpl buffer,
|
||||
@@ -2155,8 +2279,20 @@ final class JSFloat64ArrayImpl extends JSFloatArrayBase
|
||||
factory JSFloat64ArrayImpl(int length) =>
|
||||
JSFloat64ArrayImpl._(_newDataView(length * 8));
|
||||
|
||||
factory JSFloat64ArrayImpl.fromJSArray(WasmExternRef? jsArrayRef) =>
|
||||
JSFloat64ArrayImpl._(_dataViewFromJSArray(jsArrayRef));
|
||||
static bool _checkRefType(WasmExternRef? ref) =>
|
||||
js.JS<bool>('o => o instanceof Float64Array', ref);
|
||||
|
||||
factory JSFloat64ArrayImpl.fromRefUnchecked(WasmExternRef? ref) {
|
||||
assert(_checkRefType(ref));
|
||||
return JSFloat64ArrayImpl._(_dataViewFromJSArray(ref));
|
||||
}
|
||||
|
||||
factory JSFloat64ArrayImpl.fromRef(WasmExternRef? ref) {
|
||||
if (!_checkRefType(ref)) {
|
||||
return _throwConversionFailureError("Float64List");
|
||||
}
|
||||
return JSFloat64ArrayImpl.fromRefUnchecked(ref);
|
||||
}
|
||||
|
||||
factory JSFloat64ArrayImpl.view(
|
||||
JSArrayBufferImpl buffer,
|
||||
@@ -2707,3 +2843,7 @@ void _setFloat64(
|
||||
WasmF64.fromDouble(value.toDouble()),
|
||||
WasmI32.fromBool(littleEndian),
|
||||
);
|
||||
|
||||
Never _throwConversionFailureError(String expectedType) => minify
|
||||
? throw ArgumentError()
|
||||
: throw ArgumentError("JS reference cannot be converted to $expectedType");
|
||||
|
||||
@@ -13,7 +13,7 @@ String quoteStringForRegExp(String string) =>
|
||||
// This method is optimized to test before replacement, which should be
|
||||
// much faster. This might be worth measuring in real world use cases
|
||||
// though.
|
||||
JSStringImpl(
|
||||
JSStringImpl.fromRefUnchecked(
|
||||
JS<WasmExternRef>(r"""s => {
|
||||
if (/[[\]{}()*+?.\\^$|]/.test(s)) {
|
||||
s = s.replace(/[[\]{}()*+?.\\^$|]/g, '\\$&');
|
||||
@@ -132,7 +132,7 @@ class JSSyntaxRegExp implements RegExp {
|
||||
if (isJSRegExp(result)) return JSValue(result!) as JSNativeRegExp;
|
||||
// The returned value is the stringified JavaScript exception. Turn it into
|
||||
// a Dart exception.
|
||||
String errorMessage = JSStringImpl(result!);
|
||||
String errorMessage = JSStringImpl.fromRefUnchecked(result!);
|
||||
throw FormatException('Illegal RegExp pattern ($errorMessage)', source);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class StackTrace {
|
||||
// `getCurrentStackTrace` and `StackTrace.current`. On Chrome, the first
|
||||
// line is not a frame but a line with just "Error", which we also remove.
|
||||
return _StringStackTrace(
|
||||
JSStringImpl(
|
||||
JSStringImpl.fromRefUnchecked(
|
||||
JS<WasmExternRef?>(r"""() => {
|
||||
let stackString = new Error().stack.toString();
|
||||
let frames = stackString.split('\n');
|
||||
|
||||
@@ -73,7 +73,7 @@ class String {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
dst.write(i, src.readUnsigned(start + i));
|
||||
}
|
||||
return JSStringImpl(
|
||||
return JSStringImpl.fromRefUnchecked(
|
||||
jsStringFromCharCodeArray(dst, 0.toWasmI32(), count.toWasmI32()),
|
||||
);
|
||||
}
|
||||
@@ -96,7 +96,7 @@ class String {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
dst.write(i, charCodes[start + i]);
|
||||
}
|
||||
return JSStringImpl(
|
||||
return JSStringImpl.fromRefUnchecked(
|
||||
jsStringFromCharCodeArray(dst, 0.toWasmI32(), count.toWasmI32()),
|
||||
);
|
||||
}
|
||||
@@ -118,7 +118,7 @@ class String {
|
||||
end += offset;
|
||||
|
||||
final data = charCodes.data;
|
||||
return JSStringImpl(
|
||||
return JSStringImpl.fromRefUnchecked(
|
||||
jsStringFromCharCodeArray(data, start.toWasmI32(), end.toWasmI32()),
|
||||
);
|
||||
}
|
||||
@@ -146,7 +146,7 @@ class String {
|
||||
}
|
||||
dst.write(i, charCode);
|
||||
}
|
||||
return JSStringImpl(
|
||||
return JSStringImpl.fromRefUnchecked(
|
||||
jsStringFromCharCodeArray(dst, 0.toWasmI32(), count.toWasmI32()),
|
||||
);
|
||||
}
|
||||
@@ -196,7 +196,7 @@ class String {
|
||||
}
|
||||
}
|
||||
|
||||
return JSStringImpl(
|
||||
return JSStringImpl.fromRefUnchecked(
|
||||
jsStringFromCharCodeArray(list, const WasmI32(0), WasmI32.fromInt(index)),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ part of "core_patch.dart";
|
||||
class Uri {
|
||||
@patch
|
||||
static Uri get base {
|
||||
final currentUri = JSStringImpl(
|
||||
final currentUri = JSStringImpl.fromRefUnchecked(
|
||||
JS<WasmExternRef?>("""() => {
|
||||
// On browsers return `globalThis.location.href`
|
||||
if (globalThis.location != null) {
|
||||
|
||||
@@ -38,5 +38,5 @@ String _jsBigIntToString(int i, int radix) {
|
||||
WasmI64.fromInt(i),
|
||||
WasmI32.fromInt(radix),
|
||||
);
|
||||
return JSStringImpl(result);
|
||||
return JSStringImpl.fromRefUnchecked(result);
|
||||
}
|
||||
|
||||
@@ -73,17 +73,22 @@ class String {
|
||||
@patch
|
||||
factory String.fromCharCode(int charCode) => _fromCharCode(charCode);
|
||||
|
||||
static String _fromOneByteCharCode(int charCode) => JSStringImpl(
|
||||
js.JS<WasmExternRef?>('c => String.fromCharCode(c)', charCode.toDouble()),
|
||||
);
|
||||
static String _fromOneByteCharCode(int charCode) =>
|
||||
JSStringImpl.fromRefUnchecked(
|
||||
js.JS<WasmExternRef?>(
|
||||
'c => String.fromCharCode(c)',
|
||||
charCode.toDouble(),
|
||||
),
|
||||
);
|
||||
|
||||
static String _fromTwoByteCharCode(int low, int high) => JSStringImpl(
|
||||
js.JS<WasmExternRef?>(
|
||||
'(l, h) => String.fromCharCode(h, l)',
|
||||
low.toDouble(),
|
||||
high.toDouble(),
|
||||
),
|
||||
);
|
||||
static String _fromTwoByteCharCode(int low, int high) =>
|
||||
JSStringImpl.fromRefUnchecked(
|
||||
js.JS<WasmExternRef?>(
|
||||
'(l, h) => String.fromCharCode(h, l)',
|
||||
low.toDouble(),
|
||||
high.toDouble(),
|
||||
),
|
||||
);
|
||||
|
||||
static String _fromCharCode(int charCode) {
|
||||
if (0 <= charCode) {
|
||||
@@ -105,7 +110,7 @@ class String {
|
||||
int index,
|
||||
int end,
|
||||
) {
|
||||
return JSStringImpl(
|
||||
return JSStringImpl.fromRefUnchecked(
|
||||
js.JS<WasmExternRef?>(
|
||||
'(c, i, e) => String.fromCharCode.apply(null, new Uint32Array(c.buffer, c.byteOffset + i, e))',
|
||||
charCodes.toExternRef,
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
// Copyright (c) 2025, 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.
|
||||
|
||||
// dart2wasmOptions=--extra-compiler-option=--enable-experimental-wasm-interop
|
||||
|
||||
import 'dart:_js_helper';
|
||||
import 'dart:_js_types';
|
||||
import 'dart:_string';
|
||||
import 'dart:_wasm';
|
||||
import 'dart:js_interop' hide JS;
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
void main() {
|
||||
Expect.throws<ArgumentError>(
|
||||
() =>
|
||||
JSInt8ArrayImpl.fromRef(JS<WasmExternRef?>('() => new Uint8Array(10)')),
|
||||
);
|
||||
Expect.throws<ArgumentError>(
|
||||
() =>
|
||||
JSUint8ArrayImpl.fromRef(JS<WasmExternRef?>('() => new Int8Array(10)')),
|
||||
);
|
||||
Expect.throws<ArgumentError>(
|
||||
() => JSUint8ClampedArrayImpl.fromRef(
|
||||
JS<WasmExternRef?>('() => new Uint8Array(10)'),
|
||||
),
|
||||
);
|
||||
Expect.throws<ArgumentError>(
|
||||
() => JSInt16ArrayImpl.fromRef(
|
||||
JS<WasmExternRef?>('() => new Uint16Array(10)'),
|
||||
),
|
||||
);
|
||||
Expect.throws<ArgumentError>(
|
||||
() => JSUint16ArrayImpl.fromRef(
|
||||
JS<WasmExternRef?>('() => new Int16Array(10)'),
|
||||
),
|
||||
);
|
||||
Expect.throws<ArgumentError>(
|
||||
() => JSInt32ArrayImpl.fromRef(
|
||||
JS<WasmExternRef?>('() => new Uint32Array(10)'),
|
||||
),
|
||||
);
|
||||
Expect.throws<ArgumentError>(
|
||||
() => JSUint32ArrayImpl.fromRef(
|
||||
JS<WasmExternRef?>('() => new Int32Array(10)'),
|
||||
),
|
||||
);
|
||||
Expect.throws<ArgumentError>(
|
||||
() => JSFloat32ArrayImpl.fromRef(
|
||||
JS<WasmExternRef?>('() => new Float64Array(10)'),
|
||||
),
|
||||
);
|
||||
Expect.throws<ArgumentError>(
|
||||
() => JSFloat64ArrayImpl.fromRef(
|
||||
JS<WasmExternRef?>('() => new Float32Array(10)'),
|
||||
),
|
||||
);
|
||||
Expect.throws<ArgumentError>(
|
||||
() => JSArrayBufferImpl.fromRef(
|
||||
JS<WasmExternRef?>('() => new DataView(new ArrayBuffer(10))'),
|
||||
),
|
||||
);
|
||||
Expect.throws<ArgumentError>(
|
||||
() =>
|
||||
JSDataViewImpl.fromRef(JS<WasmExternRef?>('() => new ArrayBuffer(10)')),
|
||||
);
|
||||
Expect.throws<ArgumentError>(
|
||||
() => JSStringImpl.fromRef(JS<WasmExternRef?>('() => new ArrayBuffer(10)')),
|
||||
);
|
||||
Expect.throws<ArgumentError>(
|
||||
() => JSArrayImpl.fromRef(JS<WasmExternRef?>('() => "hi"')),
|
||||
);
|
||||
|
||||
final JSInt8Array jsInt8ArrayBox =
|
||||
JSValue(JS<WasmExternRef?>('() => new Uint8Array(10)')) as JSInt8Array;
|
||||
Expect.throws<ArgumentError>(() {
|
||||
final Int8List dartValue = jsInt8ArrayBox.toDart;
|
||||
});
|
||||
|
||||
final JSUint8Array jsUint8ArrayBox =
|
||||
JSValue(JS<WasmExternRef?>('() => new Int8Array(10)')) as JSUint8Array;
|
||||
Expect.throws<ArgumentError>(() {
|
||||
final Uint8List dartValue = jsUint8ArrayBox.toDart;
|
||||
});
|
||||
|
||||
final JSUint8ClampedArray jsUint8ClampedArrayBox =
|
||||
JSValue(JS<WasmExternRef?>('() => new Uint8Array(10)'))
|
||||
as JSUint8ClampedArray;
|
||||
Expect.throws<ArgumentError>(() {
|
||||
final Uint8ClampedList dartValue = jsUint8ClampedArrayBox.toDart;
|
||||
});
|
||||
|
||||
final JSInt16Array jsInt16ArrayBox =
|
||||
JSValue(JS<WasmExternRef?>('() => new Uint16Array(10)')) as JSInt16Array;
|
||||
Expect.throws<ArgumentError>(() {
|
||||
final Int16List dartValue = jsInt16ArrayBox.toDart;
|
||||
});
|
||||
|
||||
final JSUint16Array jsUint16ArrayBox =
|
||||
JSValue(JS<WasmExternRef?>('() => new Int16Array(10)')) as JSUint16Array;
|
||||
Expect.throws<ArgumentError>(() {
|
||||
final Uint16List dartValue = jsUint16ArrayBox.toDart;
|
||||
});
|
||||
|
||||
final JSInt32Array jsInt32ArrayBox =
|
||||
JSValue(JS<WasmExternRef?>('() => new Uint32Array(10)')) as JSInt32Array;
|
||||
Expect.throws<ArgumentError>(() {
|
||||
final Int32List dartValue = jsInt32ArrayBox.toDart;
|
||||
});
|
||||
|
||||
final JSUint32Array jsUint32ArrayBox =
|
||||
JSValue(JS<WasmExternRef?>('() => new Int32Array(10)')) as JSUint32Array;
|
||||
Expect.throws<ArgumentError>(() {
|
||||
final Uint32List dartValue = jsUint32ArrayBox.toDart;
|
||||
});
|
||||
|
||||
final JSFloat32Array jsFloat32ArrayBox =
|
||||
JSValue(JS<WasmExternRef?>('() => new Float64Array(10)'))
|
||||
as JSFloat32Array;
|
||||
Expect.throws<ArgumentError>(() {
|
||||
final Float32List dartValue = jsFloat32ArrayBox.toDart;
|
||||
});
|
||||
|
||||
final JSFloat64Array jsFloat64ArrayBox =
|
||||
JSValue(JS<WasmExternRef?>('() => new Float32Array(10)'))
|
||||
as JSFloat64Array;
|
||||
Expect.throws<ArgumentError>(() {
|
||||
final Float64List dartValue = jsFloat64ArrayBox.toDart;
|
||||
});
|
||||
|
||||
final JSArrayBuffer jsArrayBufferBox =
|
||||
JSValue(JS<WasmExternRef?>('() => new DataView(new ArrayBuffer(10))'))
|
||||
as JSArrayBuffer;
|
||||
Expect.throws<ArgumentError>(() {
|
||||
final ByteBuffer dartValue = jsArrayBufferBox.toDart;
|
||||
});
|
||||
|
||||
final JSDataView jsDataViewBox =
|
||||
JSValue(JS<WasmExternRef?>('() => new ArrayBuffer(10)')) as JSDataView;
|
||||
Expect.throws<ArgumentError>(() {
|
||||
final ByteData dartValue = jsDataViewBox.toDart;
|
||||
});
|
||||
|
||||
final JSString jsStringBox =
|
||||
JSValue(JS<WasmExternRef?>('() => new ArrayBuffer(10)')) as JSString;
|
||||
Expect.throws<ArgumentError>(() {
|
||||
final String dartValue = jsStringBox.toDart;
|
||||
});
|
||||
|
||||
final JSArray jsArrayBox =
|
||||
JSValue(JS<WasmExternRef?>('() => "hi"')) as JSArray;
|
||||
Expect.throws<ArgumentError>(() {
|
||||
final List dartValue = jsArrayBox.toDart;
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user