[dart2wasm] Use WasmExternRef for JS interop.

Change-Id: I01138d48ba9cc67954ef086968af90dae173fda9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/257880
Reviewed-by: Aske Simon Christensen <askesc@google.com>
Commit-Queue: Joshua Litt <joshualitt@google.com>
This commit is contained in:
Joshua Litt 2022-09-07 20:55:27 +00:00 committed by Commit Bot
parent e4643b54df
commit 708264289d
5 changed files with 170 additions and 166 deletions

View file

@ -51,7 +51,7 @@ class JsUtilWasmOptimizer extends Transformer {
final Procedure _newObjectTarget;
final Procedure _wrapDartFunctionTarget;
final Procedure _allowInteropTarget;
final Class _wasmAnyRefClass;
final Class _wasmExternRefClass;
final Class _objectClass;
final Class _pragmaClass;
final Field _pragmaName;
@ -84,7 +84,8 @@ class JsUtilWasmOptimizer extends Transformer {
_coreTypes.index.getTopLevelProcedure('dart:js_util', 'newObject'),
_allowInteropTarget =
_coreTypes.index.getTopLevelProcedure('dart:js', 'allowInterop'),
_wasmAnyRefClass = _coreTypes.index.getClass('dart:wasm', 'WasmAnyRef'),
_wasmExternRefClass =
_coreTypes.index.getClass('dart:wasm', 'WasmExternRef'),
_objectClass = _coreTypes.objectClass,
_pragmaClass = _coreTypes.pragmaClass,
_pragmaName = _coreTypes.pragmaName,
@ -255,8 +256,8 @@ class JsUtilWasmOptimizer extends Transformer {
// be exported from Wasm to JS so it can be called from JS. The argument
// returned from the supplied callback will be converted with `jsifyRaw` to
// a native JS value before being returned to JS.
DartType nullableWasmAnyRefType =
_wasmAnyRefClass.getThisType(_coreTypes, Nullability.nullable);
DartType nullableWasmExternRefType =
_wasmExternRefClass.getThisType(_coreTypes, Nullability.nullable);
final String libraryName = _library.name ?? 'Unnamed';
final functionTrampolineName =
'|_functionTrampoline${_functionTrampolineN++}For$libraryName';
@ -275,7 +276,7 @@ class JsUtilWasmOptimizer extends Transformer {
functionType: function),
]))),
positionalParameters: positionalParameters,
returnType: nullableWasmAnyRefType)
returnType: nullableWasmExternRefType)
..fileOffset = fileOffset,
isStatic: true,
fileUri: node.fileUri)

View file

@ -1408,7 +1408,7 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
@override
w.ValueType visitEqualsNull(EqualsNull node, w.ValueType expectedType) {
wrap(node.expression, const w.RefType.any(nullable: true));
wrap(node.expression, const w.RefType.top(nullable: true));
b.ref_is_null();
return w.NumType.i32;
}

View file

@ -14,77 +14,77 @@ part 'regexp_helper.dart';
/// [JSValue] is the root of the JS interop object hierarchy.
class JSValue {
final WasmAnyRef _ref;
final WasmExternRef _ref;
JSValue(this._ref);
// Currently we always explictly box JS ref's in [JSValue] objects. In the
// future, we will want to leave these values unboxed when possible, even when
// they are nullable.
static JSValue? box(WasmAnyRef? ref) =>
static JSValue? box(WasmExternRef? ref) =>
isDartNull(ref) ? null : JSValue(ref!);
@override
bool operator ==(Object that) =>
that is JSValue && areEqualInJS(_ref, that._ref);
WasmAnyRef toAnyRef() => _ref;
WasmExternRef toExternRef() => _ref;
String toString() => jsStringToDartString(_ref);
List<Object?> toObjectList() => toDartList(_ref);
Object toObject() => jsObjectToDartObject(_ref);
}
extension DoubleToJS on double {
WasmAnyRef toAnyRef() => toJSNumber(this);
JSValue toJS() => JSValue(toAnyRef());
WasmExternRef toExternRef() => toJSNumber(this)!;
JSValue toJS() => JSValue(toExternRef());
}
extension StringToJS on String {
WasmAnyRef toAnyRef() => jsStringFromDartString(this);
JSValue toJS() => JSValue(toAnyRef());
WasmExternRef toExternRef() => jsStringFromDartString(this)!;
JSValue toJS() => JSValue(toExternRef());
}
extension ListOfObjectToJS on List<Object?> {
WasmAnyRef toAnyRef() => jsArrayFromDartList(this);
JSValue toJS() => JSValue(toAnyRef());
WasmExternRef toExternRef() => jsArrayFromDartList(this)!;
JSValue toJS() => JSValue(toExternRef());
}
extension ObjectToJS on Object {
WasmAnyRef toAnyRef() => jsObjectFromDartObject(this);
JSValue toJS() => JSValue(toAnyRef());
WasmExternRef toExternRef() => jsObjectFromDartObject(this);
JSValue toJS() => JSValue(toExternRef());
}
// For now both `null` and `undefined` in JS map to `null` in Dart.
bool isDartNull(WasmAnyRef? ref) => ref == null || isJSUndefined(ref);
bool isDartNull(WasmExternRef? ref) => ref == null || isJSUndefined(ref);
/// A [JSArray] is a wrapper for a native JSArray.
class JSArray extends JSValue {
JSArray(WasmAnyRef ref) : super(ref);
JSArray(WasmExternRef ref) : super(ref);
static JSArray? box(WasmAnyRef? ref) =>
static JSArray? box(WasmExternRef? ref) =>
isDartNull(ref) ? null : JSArray(ref!);
JSValue? pop() =>
JSValue.box(callMethodVarArgsRaw(_ref, 'pop'.toAnyRef(), [].toAnyRef()));
JSValue? pop() => JSValue.box(
callMethodVarArgsRaw(_ref, 'pop'.toExternRef(), [].toExternRef()));
JSValue? operator [](int index) =>
JSValue.box(getPropertyRaw(_ref, intToJSNumber(index)));
void operator []=(int index, JSValue? value) =>
setPropertyRaw(_ref, intToJSNumber(index), value?.toAnyRef());
setPropertyRaw(_ref, intToJSNumber(index), value?.toExternRef());
int get length =>
toDartNumber(getPropertyRaw(_ref, 'length'.toAnyRef())!).floor();
toDartNumber(getPropertyRaw(_ref, 'length'.toExternRef())!).floor();
}
/// A [JSObject] is a wrapper for any JS object literal.
class JSObject extends JSValue {
JSObject(WasmAnyRef ref) : super(ref);
JSObject(WasmExternRef ref) : super(ref);
static JSObject? box(WasmAnyRef? ref) =>
static JSObject? box(WasmExternRef? ref) =>
isDartNull(ref) ? null : JSObject(ref!);
JSValue? operator [](String key) =>
JSValue.box(getPropertyRaw(_ref, key.toAnyRef()));
JSValue.box(getPropertyRaw(_ref, key.toExternRef()));
void operator []=(String key, JSValue? value) =>
setPropertyRaw(_ref, key.toAnyRef(), value?.toAnyRef());
setPropertyRaw(_ref, key.toExternRef(), value?.toExternRef());
}
class JSArrayIteratorAdapter<T> extends Iterator<T> {
@ -103,7 +103,7 @@ class JSArrayIteratorAdapter<T> extends Iterator<T> {
}
@override
T get current => dartifyRaw(array[index]?.toAnyRef()) as T;
T get current => dartifyRaw(array[index]?.toExternRef()) as T;
}
/// [JSArrayIterableAdapter] lazily adapts a [JSArray] to Dart's [Iterable]
@ -121,195 +121,197 @@ class JSArrayIterableAdapter<T> extends EfficientLengthIterable<T> {
}
// Convert to double to avoid converting to [BigInt] in the case of int64.
WasmAnyRef intToJSNumber(int i) => toJSNumber(i.toDouble());
WasmExternRef intToJSNumber(int i) => toJSNumber(i.toDouble())!;
WasmAnyRef? getConstructorString(String constructor) =>
getPropertyRaw(globalThisRaw(), constructor.toAnyRef());
WasmExternRef? getConstructorString(String constructor) =>
getPropertyRaw(globalThisRaw(), constructor.toExternRef());
Object jsObjectToDartObject(WasmAnyRef ref) => unsafeCastOpaque<Object>(ref);
Object jsObjectToDartObject(WasmExternRef? ref) =>
unsafeCastOpaque<Object>(ref.internalize());
WasmAnyRef jsObjectFromDartObject(Object object) =>
unsafeCastOpaque<WasmAnyRef>(object);
WasmExternRef jsObjectFromDartObject(Object object) =>
unsafeCastOpaque<WasmAnyRef>(object).externalize();
@pragma("wasm:import", "dart2wasm.isJSUndefined")
external bool isJSUndefined(WasmAnyRef? o);
external bool isJSUndefined(WasmExternRef? o);
@pragma("wasm:import", "dart2wasm.isJSBoolean")
external bool isJSBoolean(WasmAnyRef? o);
external bool isJSBoolean(WasmExternRef? o);
@pragma("wasm:import", "dart2wasm.isJSNumber")
external bool isJSNumber(WasmAnyRef? o);
external bool isJSNumber(WasmExternRef? o);
@pragma("wasm:import", "dart2wasm.isJSBigInt")
external bool isJSBigInt(WasmAnyRef? o);
external bool isJSBigInt(WasmExternRef? o);
@pragma("wasm:import", "dart2wasm.isJSString")
external bool isJSString(WasmAnyRef? o);
external bool isJSString(WasmExternRef? o);
@pragma("wasm:import", "dart2wasm.isJSSymbol")
external bool isJSSymbol(WasmAnyRef? o);
external bool isJSSymbol(WasmExternRef? o);
@pragma("wasm:import", "dart2wasm.isJSFunction")
external bool isJSFunction(WasmAnyRef? o);
external bool isJSFunction(WasmExternRef? o);
@pragma("wasm:import", "dart2wasm.isJSInt8Array")
external bool isJSInt8Array(WasmAnyRef object);
external bool isJSInt8Array(WasmExternRef? object);
@pragma("wasm:import", "dart2wasm.isJSUint8Array")
external bool isJSUint8Array(WasmAnyRef object);
external bool isJSUint8Array(WasmExternRef? object);
@pragma("wasm:import", "dart2wasm.isJSUint8ClampedArray")
external bool isJSUint8ClampedArray(WasmAnyRef object);
external bool isJSUint8ClampedArray(WasmExternRef? object);
@pragma("wasm:import", "dart2wasm.isJSInt16Array")
external bool isJSInt16Array(WasmAnyRef object);
external bool isJSInt16Array(WasmExternRef? object);
@pragma("wasm:import", "dart2wasm.isJSUint16Array")
external bool isJSUint16Array(WasmAnyRef object);
external bool isJSUint16Array(WasmExternRef? object);
@pragma("wasm:import", "dart2wasm.isJSInt32Array")
external bool isJSInt32Array(WasmAnyRef object);
external bool isJSInt32Array(WasmExternRef? object);
@pragma("wasm:import", "dart2wasm.isJSUint32Array")
external bool isJSUint32Array(WasmAnyRef object);
external bool isJSUint32Array(WasmExternRef? object);
@pragma("wasm:import", "dart2wasm.isJSFloat32Array")
external bool isJSFloat32Array(WasmAnyRef object);
external bool isJSFloat32Array(WasmExternRef? object);
@pragma("wasm:import", "dart2wasm.isJSFloat64Array")
external bool isJSFloat64Array(WasmAnyRef object);
external bool isJSFloat64Array(WasmExternRef? object);
@pragma("wasm:import", "dart2wasm.isJSArrayBuffer")
external bool isJSArrayBuffer(WasmAnyRef object);
external bool isJSArrayBuffer(WasmExternRef? object);
@pragma("wasm:import", "dart2wasm.isJSDataView")
external bool isJSDataView(WasmAnyRef object);
external bool isJSDataView(WasmExternRef? object);
@pragma("wasm:import", "dart2wasm.isJSArray")
external bool isJSArray(WasmAnyRef? o);
external bool isJSArray(WasmExternRef? o);
@pragma("wasm:import", "dart2wasm.isJSWrappedDartFunction")
external bool isJSWrappedDartFunction(WasmAnyRef? o);
external bool isJSWrappedDartFunction(WasmExternRef? o);
@pragma("wasm:import", "dart2wasm.isJSObject")
external bool isJSObject(WasmAnyRef? o);
external bool isJSObject(WasmExternRef? o);
@pragma("wasm:import", "dart2wasm.isJSSimpleObject")
external bool isJSSimpleObject(WasmAnyRef? o);
external bool isJSSimpleObject(WasmExternRef? o);
@pragma("wasm:import", "dart2wasm.isJSRegExp")
external bool isJSRegExp(WasmAnyRef object);
external bool isJSRegExp(WasmExternRef? object);
@pragma("wasm:import", "dart2wasm.areEqualInJS")
external bool areEqualInJS(WasmAnyRef? l, WasmAnyRef? r);
external bool areEqualInJS(WasmExternRef? l, WasmExternRef? r);
// The JS runtime will run helpful conversion routines between refs and bool /
// double. In the longer term hopefully we can find a way to avoid the round
// trip.
@pragma("wasm:import", "dart2wasm.roundtrip")
external double toDartNumber(WasmAnyRef ref);
external double toDartNumber(WasmExternRef? ref);
@pragma("wasm:import", "dart2wasm.roundtrip")
external WasmAnyRef toJSNumber(double d);
external WasmExternRef? toJSNumber(double d);
@pragma("wasm:import", "dart2wasm.roundtrip")
external bool toDartBool(WasmAnyRef ref);
external bool toDartBool(WasmExternRef? ref);
@pragma("wasm:import", "dart2wasm.toJSBoolean")
external WasmAnyRef toJSBoolean(bool b);
external WasmExternRef? toJSBoolean(bool b);
@pragma("wasm:import", "dart2wasm.objectLength")
external double objectLength(WasmAnyRef ref);
external double objectLength(WasmExternRef? ref);
@pragma("wasm:import", "dart2wasm.objectReadIndex")
external WasmAnyRef? objectReadIndex(WasmAnyRef ref, int index);
external WasmExternRef? objectReadIndex(WasmExternRef? ref, int index);
@pragma("wasm:import", "dart2wasm.unwrapJSWrappedDartFunction")
external Object? unwrapJSWrappedDartFunction(WasmAnyRef f);
external Object? unwrapJSWrappedDartFunction(WasmExternRef? f);
@pragma("wasm:import", "dart2wasm.int8ArrayFromDartInt8List")
external WasmAnyRef jsInt8ArrayFromDartInt8List(Int8List list);
external WasmExternRef? jsInt8ArrayFromDartInt8List(Int8List list);
@pragma("wasm:import", "dart2wasm.uint8ArrayFromDartUint8List")
external WasmAnyRef jsUint8ArrayFromDartUint8List(Uint8List list);
external WasmExternRef? jsUint8ArrayFromDartUint8List(Uint8List list);
@pragma("wasm:import", "dart2wasm.uint8ClampedArrayFromDartUint8ClampedList")
external WasmAnyRef jsUint8ClampedArrayFromDartUint8ClampedList(
external WasmExternRef? jsUint8ClampedArrayFromDartUint8ClampedList(
Uint8ClampedList list);
@pragma("wasm:import", "dart2wasm.int16ArrayFromDartInt16List")
external WasmAnyRef jsInt16ArrayFromDartInt16List(Int16List list);
external WasmExternRef? jsInt16ArrayFromDartInt16List(Int16List list);
@pragma("wasm:import", "dart2wasm.uint16ArrayFromDartUint16List")
external WasmAnyRef jsUint16ArrayFromDartUint16List(Uint16List list);
external WasmExternRef? jsUint16ArrayFromDartUint16List(Uint16List list);
@pragma("wasm:import", "dart2wasm.int32ArrayFromDartInt32List")
external WasmAnyRef jsInt32ArrayFromDartInt32List(Int32List list);
external WasmExternRef? jsInt32ArrayFromDartInt32List(Int32List list);
@pragma("wasm:import", "dart2wasm.uint32ArrayFromDartUint32List")
external WasmAnyRef jsUint32ArrayFromDartUint32List(Uint32List list);
external WasmExternRef? jsUint32ArrayFromDartUint32List(Uint32List list);
@pragma("wasm:import", "dart2wasm.float32ArrayFromDartFloat32List")
external WasmAnyRef jsFloat32ArrayFromDartFloat32List(Float32List list);
external WasmExternRef? jsFloat32ArrayFromDartFloat32List(Float32List list);
@pragma("wasm:import", "dart2wasm.float64ArrayFromDartFloat64List")
external WasmAnyRef jsFloat64ArrayFromDartFloat64List(Float64List list);
external WasmExternRef? jsFloat64ArrayFromDartFloat64List(Float64List list);
@pragma("wasm:import", "dart2wasm.dataViewFromDartByteData")
external WasmAnyRef jsDataViewFromDartByteData(
external WasmExternRef? jsDataViewFromDartByteData(
ByteData data, double byteLength);
@pragma("wasm:import", "dart2wasm.arrayFromDartList")
external WasmAnyRef jsArrayFromDartList(List<Object?> list);
external WasmExternRef? jsArrayFromDartList(List<Object?> list);
@pragma("wasm:import", "dart2wasm.stringFromDartString")
external WasmAnyRef jsStringFromDartString(String string);
external WasmExternRef? jsStringFromDartString(String string);
@pragma("wasm:import", "dart2wasm.stringToDartString")
external String jsStringToDartString(WasmAnyRef string);
external String jsStringToDartString(WasmExternRef? string);
@pragma("wasm:import", "dart2wasm.eval")
external void evalRaw(WasmAnyRef code);
external void evalRaw(WasmExternRef? code);
@pragma("wasm:import", "dart2wasm.newObject")
external WasmAnyRef newObjectRaw();
external WasmExternRef? newObjectRaw();
@pragma("wasm:import", "dart2wasm.newArray")
external WasmAnyRef newArrayRaw();
external WasmExternRef? newArrayRaw();
@pragma("wasm:import", "dart2wasm.globalThis")
external WasmAnyRef globalThisRaw();
external WasmExternRef? globalThisRaw();
@pragma("wasm:import", "dart2wasm.callConstructorVarArgs")
external WasmAnyRef callConstructorVarArgsRaw(WasmAnyRef o, WasmAnyRef args);
external WasmExternRef? callConstructorVarArgsRaw(
WasmExternRef? o, WasmExternRef? args);
@pragma("wasm:import", "dart2wasm.safeCallConstructorVarArgs")
external WasmAnyRef safeCallConstructorVarArgsRaw(
WasmAnyRef o, WasmAnyRef args);
external WasmExternRef? safeCallConstructorVarArgsRaw(
WasmExternRef? o, WasmExternRef? args);
@pragma("wasm:import", "dart2wasm.hasProperty")
external bool hasPropertyRaw(WasmAnyRef o, WasmAnyRef name);
external bool hasPropertyRaw(WasmExternRef? o, WasmExternRef? name);
@pragma("wasm:import", "dart2wasm.getProperty")
external WasmAnyRef? getPropertyRaw(WasmAnyRef o, WasmAnyRef name);
external WasmExternRef? getPropertyRaw(WasmExternRef? o, WasmExternRef? name);
@pragma("wasm:import", "dart2wasm.setProperty")
external WasmAnyRef? setPropertyRaw(
WasmAnyRef o, WasmAnyRef name, WasmAnyRef? value);
external WasmExternRef? setPropertyRaw(
WasmExternRef? o, WasmExternRef? name, WasmExternRef? value);
@pragma("wasm:import", "dart2wasm.callMethodVarArgs")
external WasmAnyRef? callMethodVarArgsRaw(
WasmAnyRef o, WasmAnyRef method, WasmAnyRef? args);
external WasmExternRef? callMethodVarArgsRaw(
WasmExternRef? o, WasmExternRef? method, WasmExternRef? args);
@pragma("wasm:import", "dart2wasm.stringify")
external String stringify(WasmAnyRef? object);
external String stringify(WasmExternRef? object);
@pragma("wasm:import", "dart2wasm.objectKeys")
external WasmAnyRef objectKeysRaw(WasmAnyRef? o);
external WasmExternRef? objectKeysRaw(WasmExternRef? o);
@pragma("wasm:import", "dart2wasm.promiseThen")
external void promiseThen(
WasmAnyRef promise, WasmAnyRef successFunc, WasmAnyRef failureFunc);
external void promiseThen(WasmExternRef? promise, WasmExternRef? successFunc,
WasmExternRef? failureFunc);
// Currently, `allowInterop` returns a Function type. This is unfortunate for
// Dart2wasm because it means arbitrary Dart functions can flow to JS util
@ -319,14 +321,14 @@ external void promiseThen(
// NOTE: We are not currently replacing functions returned from JS.
Map<Function, JSValue> functionToJSWrapper = {};
WasmAnyRef jsArrayBufferFromDartByteBuffer(ByteBuffer buffer) {
WasmExternRef? jsArrayBufferFromDartByteBuffer(ByteBuffer buffer) {
ByteData byteData = ByteData.view(buffer);
WasmAnyRef dataView =
WasmExternRef? dataView =
jsDataViewFromDartByteData(byteData, byteData.lengthInBytes.toDouble());
return getPropertyRaw(dataView, 'buffer'.toAnyRef())!;
return getPropertyRaw(dataView, 'buffer'.toExternRef());
}
WasmAnyRef? jsifyRaw(Object? object) {
WasmExternRef? jsifyRaw(Object? object) {
if (object == null) {
return null;
} else if (object is bool) {
@ -334,9 +336,9 @@ WasmAnyRef? jsifyRaw(Object? object) {
} else if (object is Function) {
assert(functionToJSWrapper.containsKey(object),
'Must call `allowInterop` on functions before they flow to JS');
return functionToJSWrapper[object]?.toAnyRef();
return functionToJSWrapper[object]?.toExternRef();
} else if (object is JSValue) {
return object.toAnyRef();
return object.toExternRef();
} else if (object is String) {
return jsStringFromDartString(object);
} else if (object is Int8List) {
@ -374,9 +376,9 @@ WasmAnyRef? jsifyRaw(Object? object) {
/// cast error for certain oddball types(I think undefined, but need to dig
/// deeper).
@pragma("wasm:export", "\$dartifyRaw")
Object? dartifyExported(WasmAnyRef? ref) => dartifyRaw(ref);
Object? dartifyExported(WasmExternRef? ref) => dartifyRaw(ref);
Object? dartifyRaw(WasmAnyRef? ref) {
Object? dartifyRaw(WasmExternRef? ref) {
if (ref == null) {
return null;
} else if (isJSUndefined(ref)) {
@ -426,112 +428,114 @@ Object? dartifyRaw(WasmAnyRef? ref) {
}
}
Int8List toDartInt8List(WasmAnyRef ref) =>
Int8List toDartInt8List(WasmExternRef? ref) =>
jsIntTypedArrayToDartIntTypedData(ref, (size) => Int8List(size))
as Int8List;
Uint8List toDartUint8List(WasmAnyRef ref) =>
Uint8List toDartUint8List(WasmExternRef? ref) =>
jsIntTypedArrayToDartIntTypedData(ref, (size) => Uint8List(size))
as Uint8List;
Uint8ClampedList toDartUint8ClampedList(WasmAnyRef ref) =>
Uint8ClampedList toDartUint8ClampedList(WasmExternRef? ref) =>
jsIntTypedArrayToDartIntTypedData(ref, (size) => Uint8ClampedList(size))
as Uint8ClampedList;
Int16List toDartInt16List(WasmAnyRef ref) =>
Int16List toDartInt16List(WasmExternRef? ref) =>
jsIntTypedArrayToDartIntTypedData(ref, (size) => Int16List(size))
as Int16List;
Uint16List toDartUint16List(WasmAnyRef ref) =>
Uint16List toDartUint16List(WasmExternRef? ref) =>
jsIntTypedArrayToDartIntTypedData(ref, (size) => Uint16List(size))
as Uint16List;
Int32List toDartInt32List(WasmAnyRef ref) =>
Int32List toDartInt32List(WasmExternRef? ref) =>
jsIntTypedArrayToDartIntTypedData(ref, (size) => Int32List(size))
as Int32List;
Uint32List toDartUint32List(WasmAnyRef ref) =>
Uint32List toDartUint32List(WasmExternRef? ref) =>
jsIntTypedArrayToDartIntTypedData(ref, (size) => Uint32List(size))
as Uint32List;
Float32List toDartFloat32List(WasmAnyRef ref) =>
Float32List toDartFloat32List(WasmExternRef? ref) =>
jsFloatTypedArrayToDartFloatTypedData(ref, (size) => Float32List(size))
as Float32List;
Float64List toDartFloat64List(WasmAnyRef ref) =>
Float64List toDartFloat64List(WasmExternRef? ref) =>
jsFloatTypedArrayToDartFloatTypedData(ref, (size) => Float64List(size))
as Float64List;
ByteBuffer toDartByteBuffer(WasmAnyRef ref) =>
ByteBuffer toDartByteBuffer(WasmExternRef? ref) =>
toDartByteData(callConstructorVarArgsRaw(
getConstructorString('DataView')!, [JSValue(ref)].toAnyRef()))
getConstructorString('DataView'), [JSValue.box(ref)].toExternRef()))
.buffer;
ByteData toDartByteData(WasmAnyRef ref) {
ByteData toDartByteData(WasmExternRef? ref) {
int length =
toDartNumber(getPropertyRaw(ref, 'byteLength'.toAnyRef())!).toInt();
toDartNumber(getPropertyRaw(ref, 'byteLength'.toExternRef())).toInt();
ByteData data = ByteData(length);
for (int i = 0; i < length; i++) {
data.setUint8(
i,
toDartNumber(callMethodVarArgsRaw(
ref, 'getUint8'.toAnyRef(), [i].toAnyRef())!)
ref, 'getUint8'.toExternRef(), [i].toExternRef()))
.toInt());
}
return data;
}
List<double> jsFloatTypedArrayToDartFloatTypedData(
WasmAnyRef ref, List<double> makeTypedData(int size)) {
WasmExternRef? ref, List<double> makeTypedData(int size)) {
int length = objectLength(ref).toInt();
List<double> list = makeTypedData(length);
for (int i = 0; i < length; i++) {
list[i] = toDartNumber(objectReadIndex(ref, i)!);
list[i] = toDartNumber(objectReadIndex(ref, i));
}
return list;
}
List<int> jsIntTypedArrayToDartIntTypedData(
WasmAnyRef ref, List<int> makeTypedData(int size)) {
WasmExternRef? ref, List<int> makeTypedData(int size)) {
int length = objectLength(ref).toInt();
List<int> list = makeTypedData(length);
for (int i = 0; i < length; i++) {
list[i] = toDartNumber(objectReadIndex(ref, i)!).toInt();
list[i] = toDartNumber(objectReadIndex(ref, i)).toInt();
}
return list;
}
List<Object?> toDartList(WasmAnyRef ref) => List<Object?>.generate(
List<Object?> toDartList(WasmExternRef? ref) => List<Object?>.generate(
objectLength(ref).round(), (int n) => dartifyRaw(objectReadIndex(ref, n)));
@pragma("wasm:import", "dart2wasm.wrapDartFunction")
external WasmAnyRef _wrapDartFunctionRaw(
WasmAnyRef dartFunction, WasmAnyRef trampolineName);
external WasmExternRef? _wrapDartFunctionRaw(
WasmExternRef? dartFunction, WasmExternRef? trampolineName);
F _wrapDartFunction<F extends Function>(F f, String trampolineName) {
if (functionToJSWrapper.containsKey(f)) {
return f;
}
JSValue wrappedFunction = JSValue(_wrapDartFunctionRaw(
f.toJS().toAnyRef(), trampolineName.toJS().toAnyRef()));
f.toJS().toExternRef(), trampolineName.toJS().toExternRef())!);
functionToJSWrapper[f] = wrappedFunction;
return f;
}
/// Returns the JS constructor object for a given [String].
WasmAnyRef getConstructorRaw(String name) =>
getPropertyRaw(globalThisRaw(), name.toAnyRef())!;
WasmExternRef? getConstructorRaw(String name) =>
getPropertyRaw(globalThisRaw(), name.toExternRef());
/// Equivalent to `Object.keys(object)`.
JSArray objectKeys(JSValue object) => JSArray(callMethodVarArgsRaw(
getConstructorRaw('Object'), 'keys'.toAnyRef(), [object].toAnyRef())!);
getConstructorRaw('Object'),
'keys'.toExternRef(),
[object].toExternRef())!);
/// Methods used by the wasm runtime.
@pragma("wasm:export", "\$listLength")
double _listLength(List list) => list.length.toDouble();
@pragma("wasm:export", "\$listRead")
WasmAnyRef? _listRead(List<Object?> list, double index) =>
WasmExternRef? _listRead(List<Object?> list, double index) =>
jsifyRaw(list[index.toInt()]);
@pragma("wasm:export", "\$byteDataGetUint8")

View file

@ -47,8 +47,8 @@ dynamic jsify(Object? object) {
convertedObjects[o] = convertedMap;
for (final key in o.keys) {
JSValue convertedKey = convert(key) as JSValue;
setPropertyRaw(convertedMap.toAnyRef(), convertedKey.toAnyRef(),
(convert(o[key]) as JSValue).toAnyRef());
setPropertyRaw(convertedMap.toExternRef(), convertedKey.toExternRef(),
(convert(o[key]) as JSValue).toExternRef());
}
return convertedMap;
} else if (o is Iterable) {
@ -68,37 +68,36 @@ dynamic jsify(Object? object) {
}
@patch
Object get globalThis => JSValue(globalThisRaw());
Object get globalThis => JSValue(globalThisRaw()!);
@patch
T newObject<T>() => JSValue(newObjectRaw()) as T;
T newObject<T>() => JSValue(newObjectRaw()!) as T;
JSValue _newArray() => JSValue(newArrayRaw());
JSValue _newArray() => JSValue(newArrayRaw()!);
@patch
bool hasProperty(Object o, String name) =>
hasPropertyRaw(jsifyRaw(o)!, name.toJS().toAnyRef());
hasPropertyRaw(jsifyRaw(o)!, name.toJS().toExternRef());
@patch
T getProperty<T>(Object o, String name) =>
dartifyRaw(getPropertyRaw(jsifyRaw(o)!, name.toJS().toAnyRef())) as T;
dartifyRaw(getPropertyRaw(jsifyRaw(o)!, name.toJS().toExternRef())) as T;
@patch
T setProperty<T>(Object o, String name, T? value) => dartifyRaw(
setPropertyRaw(jsifyRaw(o)!, name.toJS().toAnyRef(), jsifyRaw(value))) as T;
T setProperty<T>(Object o, String name, T? value) => dartifyRaw(setPropertyRaw(
jsifyRaw(o)!, name.toJS().toExternRef(), jsifyRaw(value))) as T;
@patch
T callMethod<T>(Object o, String method, List<Object?> args) =>
dartifyRaw(callMethodVarArgsRaw(
jsifyRaw(o)!, method.toJS().toAnyRef(), args.toJS().toAnyRef())) as T;
dartifyRaw(callMethodVarArgsRaw(jsifyRaw(o)!, method.toJS().toExternRef(),
args.toJS().toExternRef())) as T;
@patch
bool instanceof(Object? o, Object type) => throw 'unimplemented';
@patch
T callConstructor<T>(Object o, List<Object?> args) =>
dartifyRaw(callConstructorVarArgsRaw(jsifyRaw(o)!, args.toJS().toAnyRef()))!
as T;
T callConstructor<T>(Object o, List<Object?> args) => dartifyRaw(
callConstructorVarArgsRaw(jsifyRaw(o)!, args.toJS().toExternRef()))! as T;
@patch
T add<T>(Object? first, Object? second) => throw 'unimplemented';
@ -192,7 +191,7 @@ Object? dartify(Object? object) {
return o;
}
WasmAnyRef ref = o.toAnyRef();
WasmExternRef ref = o.toExternRef();
if (isJSBoolean(ref) ||
isJSNumber(ref) ||
isJSString(ref) ||
@ -225,7 +224,7 @@ Object? dartify(Object? object) {
Object? key = keys[i];
if (key != null) {
dartMap[key] = convert(
JSValue.box(getPropertyRaw(ref, (key as String).toAnyRef())));
JSValue.box(getPropertyRaw(ref, (key as String).toExternRef())));
}
}
return dartMap;

View file

@ -15,39 +15,39 @@ part of dart._js_helper;
external String quoteStringForRegExp(String string);
class JSNativeMatch extends JSArray {
JSNativeMatch(WasmAnyRef ref) : super(ref);
JSNativeMatch(WasmExternRef ref) : super(ref);
static JSNativeMatch? box(WasmAnyRef? ref) =>
static JSNativeMatch? box(WasmExternRef? ref) =>
isDartNull(ref) ? null : JSNativeMatch(ref!);
String get input => jsStringToDartString(
getPropertyRaw(this.toAnyRef(), 'input'.toAnyRef())!);
getPropertyRaw(this.toExternRef(), 'input'.toExternRef())!);
int get index =>
toDartNumber(getPropertyRaw(this.toAnyRef(), 'index'.toAnyRef())!)
toDartNumber(getPropertyRaw(this.toExternRef(), 'index'.toExternRef())!)
.floor();
JSObject? get groups =>
JSObject.box(getPropertyRaw(this.toAnyRef(), 'groups'.toAnyRef()));
JSObject.box(getPropertyRaw(this.toExternRef(), 'groups'.toExternRef()));
}
class JSNativeRegExp extends JSValue {
JSNativeRegExp(WasmAnyRef ref) : super(ref);
JSNativeRegExp(WasmExternRef ref) : super(ref);
JSNativeMatch? exec(String string) => JSNativeMatch.box(callMethodVarArgsRaw(
this.toAnyRef(), 'exec'.toAnyRef(), [string].toAnyRef()));
this.toExternRef(), 'exec'.toExternRef(), [string].toExternRef()));
bool test(String string) => toDartBool(callMethodVarArgsRaw(
this.toAnyRef(), 'test'.toAnyRef(), [string].toAnyRef())!);
this.toExternRef(), 'test'.toExternRef(), [string].toExternRef())!);
String get flags => jsStringToDartString(
getPropertyRaw(this.toAnyRef(), 'flags'.toAnyRef())!);
bool get multiline =>
toDartBool(getPropertyRaw(this.toAnyRef(), 'multiline'.toAnyRef())!);
bool get ignoreCase =>
toDartBool(getPropertyRaw(this.toAnyRef(), 'ignoreCase'.toAnyRef())!);
getPropertyRaw(this.toExternRef(), 'flags'.toExternRef())!);
bool get multiline => toDartBool(
getPropertyRaw(this.toExternRef(), 'multiline'.toExternRef())!);
bool get ignoreCase => toDartBool(
getPropertyRaw(this.toExternRef(), 'ignoreCase'.toExternRef())!);
bool get unicode =>
toDartBool(getPropertyRaw(this.toAnyRef(), 'unicode'.toAnyRef())!);
toDartBool(getPropertyRaw(this.toExternRef(), 'unicode'.toExternRef())!);
bool get dotAll =>
toDartBool(getPropertyRaw(this.toAnyRef(), 'dotAll'.toAnyRef())!);
toDartBool(getPropertyRaw(this.toExternRef(), 'dotAll'.toExternRef())!);
set lastIndex(int start) => setPropertyRaw(
this.toAnyRef(), 'lastIndex'.toAnyRef(), intToJSNumber(start));
this.toExternRef(), 'lastIndex'.toExternRef(), intToJSNumber(start));
}
class JSSyntaxRegExp implements RegExp {
@ -99,9 +99,9 @@ class JSSyntaxRegExp implements RegExp {
String modifiers = '$m$i$u$s$g';
// The call to create the regexp is wrapped in a try catch so we can
// reformat the exception if need be.
WasmAnyRef result = safeCallConstructorVarArgsRaw(
getConstructorRaw('RegExp'), [source, modifiers].toAnyRef());
if (isJSRegExp(result)) return JSNativeRegExp(result);
WasmExternRef? result = safeCallConstructorVarArgsRaw(
getConstructorRaw('RegExp'), [source, modifiers].toExternRef());
if (isJSRegExp(result)) return JSNativeRegExp(result!);
// The returned value is the stringified JavaScript exception. Turn it into
// a Dart exception.
String errorMessage = jsStringToDartString(result);
@ -194,7 +194,7 @@ class _MatchImplementation implements RegExpMatch {
if (groups != null) {
JSValue? result = groups[name];
if (result != null ||
hasPropertyRaw(groups.toAnyRef(), name.toAnyRef())) {
hasPropertyRaw(groups.toExternRef(), name.toExternRef())) {
return result?.toString();
}
}