[js_types] Migrate Dart2Wasm internal interop classes to JS types. Change-Id: I0cd2ca8d7b254372818beb5af66662dc276dd29e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/288640 Commit-Queue: Joshua Litt <joshualitt@google.com> Reviewed-by: Srujan Gaddam <srujzs@google.com>
diff --git a/sdk/lib/_internal/wasm/lib/js_helper.dart b/sdk/lib/_internal/wasm/lib/js_helper.dart index facfa60..11aa9dd 100644 --- a/sdk/lib/_internal/wasm/lib/js_helper.dart +++ b/sdk/lib/_internal/wasm/lib/js_helper.dart
@@ -59,27 +59,27 @@ String toString() => stringify(_ref); // Overrides to avoid using [ObjectToJS]. - WasmExternRef? toExternRef() => _ref; - JSValue toJS() => this; + WasmExternRef? get toExternRef => _ref; } -// TODO(joshualitt): Delete these now that we have JS types. extension DoubleToJS on double { - WasmExternRef toExternRef() => toJSNumber(this)!; + WasmExternRef get toExternRef => toJSNumber(this)!; } extension StringToJS on String { - WasmExternRef toExternRef() => jsStringFromDartString(this)!; - JSValue toJS() => JSValue(toExternRef()); + WasmExternRef get toExternRef => jsStringFromDartString(this)!; } extension ListOfObjectToJS on List<Object?> { - WasmExternRef toExternRef() => jsArrayFromDartList(this)!; - JSValue toJS() => JSValue(toExternRef()); + WasmExternRef get toExternRef => jsArrayFromDartList(this)!; } extension ObjectToJS on Object { - WasmExternRef toExternRef() => jsObjectFromDartObject(this); + WasmExternRef get toExternRef => jsObjectFromDartObject(this); +} + +extension JSAnyToExtern on JSAny { + WasmExternRef? get toExternRef => (this as JSValue).toExternRef; } // For `dartify` and `jsify`, we match the conflation of `JSUndefined`, `JSNull` @@ -87,17 +87,16 @@ bool isDartNull(WasmExternRef? ref) => ref.isNull || isJSUndefined(ref); // Extensions for [JSArray] and [JSObject]. -// TODO(joshualitt): Rewrite using JS types. extension JSArrayExtension on JSArray { - external Object? pop(); - external Object? operator [](int index); - external void operator []=(int index, Object? value); - external int get length; + external JSAny? pop(); + external JSAny? operator [](JSNumber index); + external void operator []=(JSNumber index, JSAny? value); + external JSNumber get length; } extension JSObjectExtension on JSObject { - external Object? operator [](String key); - external void operator []=(String key, Object? value); + external JSAny? operator [](JSString key); + external void operator []=(JSString key, JSAny? value); } class JSArrayIteratorAdapter<T> extends Iterator<T> { @@ -109,14 +108,15 @@ @override bool moveNext() { index++; - if (index > array.length) { + int length = array.length.toDart.toInt(); + if (index > length) { throw 'Iterator out of bounds'; } - return index < array.length; + return index < length; } @override - T get current => dartifyRaw(array[index]?.toExternRef()) as T; + T get current => dartifyRaw(array[index.toJS]?.toExternRef) as T; } /// [JSArrayIterableAdapter] lazily adapts a [JSArray] to Dart's [Iterable] @@ -130,14 +130,14 @@ Iterator<T> get iterator => JSArrayIteratorAdapter<T>(array); @override - int get length => array.length; + int get length => array.length.toDart.toInt(); } // Convert to double to avoid converting to [BigInt] in the case of int64. WasmExternRef intToJSNumber(int i) => toJSNumber(i.toDouble())!; WasmExternRef? getConstructorString(String constructor) => - getPropertyRaw(globalThisRaw(), constructor.toExternRef()); + getPropertyRaw(globalThisRaw(), constructor.toExternRef); Object jsObjectToDartObject(WasmExternRef? ref) => unsafeCastOpaque<Object>(ref.internalize()); @@ -327,7 +327,7 @@ ByteData byteData = ByteData.view(buffer); WasmExternRef? dataView = jsDataViewFromDartByteData(byteData, byteData.lengthInBytes.toDouble()); - return getPropertyRaw(dataView, 'buffer'.toExternRef()); + return getPropertyRaw(dataView, 'buffer'.toExternRef); } WasmExternRef? jsifyRaw(Object? object) { @@ -338,9 +338,9 @@ } else if (object is Function) { assert(functionToJSWrapper.containsKey(object), 'Must call `allowInterop` on functions before they flow to JS'); - return functionToJSWrapper[object]?.toExternRef(); + return functionToJSWrapper[object]!.toExternRef; } else if (object is JSValue) { - return object.toExternRef(); + return object.toExternRef; } else if (object is String) { return jsStringFromDartString(object); } else if (object is Int8List) { @@ -456,18 +456,18 @@ ByteBuffer toDartByteBuffer(WasmExternRef? ref) => toDartByteData(callConstructorVarArgsRaw( - getConstructorString('DataView'), [JSValue(ref)].toExternRef())) + getConstructorString('DataView'), [JSValue(ref)].toExternRef)) .buffer; ByteData toDartByteData(WasmExternRef? ref) { int length = - toDartNumber(getPropertyRaw(ref, 'byteLength'.toExternRef())).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'.toExternRef(), [i].toExternRef())) + ref, 'getUint8'.toExternRef, [i].toExternRef)) .toInt()); } return data; @@ -495,9 +495,9 @@ JSArray toJSArray(List<JSAny?> list) { int length = list.length; - JSArray result = JSArray.withLength(length.toDouble().toJS); + JSArray result = JSArray.withLength(length.toJS); for (int i = 0; i < length; i++) { - result[i] = list[i]; + result[i.toJS] = list[i]; } return result; } @@ -522,13 +522,12 @@ /// Returns the JS constructor object for a given [String]. WasmExternRef? getConstructorRaw(String name) => - getPropertyRaw(globalThisRaw(), name.toExternRef()); + getPropertyRaw(globalThisRaw(), name.toExternRef); /// Equivalent to `Object.keys(object)`. -JSArray objectKeys(JSObject object) => JSValue(callMethodVarArgsRaw( - getConstructorRaw('Object'), - 'keys'.toExternRef(), - [object].toExternRef())!) as JSArray; +// TODO(joshualitt): Make this a static helper on 'JSObject'. +@js.JS('Object.keys') +external JSArray objectKeys(JSObject object); /// Takes a [codeTemplate] string which must represent a valid JS function, and /// a list of optional arguments. The [codeTemplate] will be inserted into the
diff --git a/sdk/lib/_internal/wasm/lib/js_interop_patch.dart b/sdk/lib/_internal/wasm/lib/js_interop_patch.dart index 5038360..38abb41 100644 --- a/sdk/lib/_internal/wasm/lib/js_interop_patch.dart +++ b/sdk/lib/_internal/wasm/lib/js_interop_patch.dart
@@ -13,7 +13,6 @@ /// Some helpers for working with JS types internally. If we implement the JS /// types as inline classes then these should go away. /// TODO(joshualitt): Find a way to get rid of the explicit casts. -WasmExternRef? _ref<T>(T o) => (o as JSValue).toExternRef(); T _box<T>(WasmExternRef? ref) => JSValue(ref) as T; /// Helper for working with the [JSAny?] top type in a backend agnostic way. @@ -22,17 +21,16 @@ // reified `JSUndefined` and `JSNull`, we have to handle the case where // `this == null`. However, after migration we can remove these checks. @patch - bool get isUndefined => this == null || isJSUndefined(_ref<JSAny>(this!)); + bool get isUndefined => this == null || isJSUndefined(this?.toExternRef); @patch - bool get isNull => this == null || _ref<JSAny>(this!).isNull; + bool get isNull => this == null || this!.toExternRef.isNull; } /// [JSExportedDartFunction] <-> [Function] extension JSExportedDartFunctionToFunction on JSExportedDartFunction { @patch - Function get toDart => - unwrapJSWrappedDartFunction(_ref<JSExportedDartFunction>(this)); + Function get toDart => unwrapJSWrappedDartFunction(toExternRef); } extension FunctionToJSExportedDartFunction on Function { @@ -43,7 +41,7 @@ /// [JSExportedDartObject], [JSOpaqueDartObject] <-> [Object] extension JSExportedDartObjectToObject on JSExportedDartObject { @patch - Object get toDart => jsObjectToDartObject(_ref<JSExportedDartObject>(this)); + Object get toDart => jsObjectToDartObject(toExternRef); } extension ObjectToJSExportedDartObject on Object { @@ -71,7 +69,7 @@ } return completer.completeError(e); }.toJS; - promiseThen(_ref(this), _ref(success), _ref(error)); + promiseThen(toExternRef, success.toExternRef, error.toExternRef); return completer.future; } } @@ -79,7 +77,7 @@ /// [JSArrayBuffer] <-> [ByteBuffer] extension JSArrayBufferToByteBuffer on JSArrayBuffer { @patch - ByteBuffer get toDart => toDartByteBuffer(_ref<JSArrayBuffer>(this)); + ByteBuffer get toDart => toDartByteBuffer(toExternRef); } extension ByteBufferToJSArrayBuffer on ByteBuffer { @@ -91,7 +89,7 @@ /// [JSDataView] <-> [ByteData] extension JSDataViewToByteData on JSDataView { @patch - ByteData get toDart => toDartByteData(_ref<JSDataView>(this)); + ByteData get toDart => toDartByteData(toExternRef); } extension ByteDataToJSDataView on ByteData { @@ -103,7 +101,7 @@ /// [JSInt8Array] <-> [Int8List] extension JSInt8ArrayToInt8List on JSInt8Array { @patch - Int8List get toDart => toDartInt8List(_ref<JSInt8Array>(this)); + Int8List get toDart => toDartInt8List(toExternRef); } extension Int8ListToJSInt8Array on Int8List { @@ -114,7 +112,7 @@ /// [JSUint8Array] <-> [Uint8List] extension JSUint8ArrayToUint8List on JSUint8Array { @patch - Uint8List get toDart => toDartUint8List(_ref<JSUint8Array>(this)); + Uint8List get toDart => toDartUint8List(toExternRef); } extension Uint8ListToJSUint8Array on Uint8List { @@ -126,8 +124,7 @@ /// [JSUint8ClampedArray] <-> [Uint8ClampedList] extension JSUint8ClampedArrayToUint8ClampedList on JSUint8ClampedArray { @patch - Uint8ClampedList get toDart => - toDartUint8ClampedList(_ref<JSUint8ClampedArray>(this)); + Uint8ClampedList get toDart => toDartUint8ClampedList(toExternRef); } extension Uint8ClampedListToJSUint8ClampedArray on Uint8ClampedList { @@ -139,7 +136,7 @@ /// [JSInt16Array] <-> [Int16List] extension JSInt16ArrayToInt16List on JSInt16Array { @patch - Int16List get toDart => toDartInt16List(_ref<JSInt16Array>(this)); + Int16List get toDart => toDartInt16List(toExternRef); } extension Int16ListToJSInt16Array on Int16List { @@ -151,7 +148,7 @@ /// [JSUint16Array] <-> [Uint16List] extension JSUint16ArrayToInt16List on JSUint16Array { @patch - Uint16List get toDart => toDartUint16List(_ref<JSUint16Array>(this)); + Uint16List get toDart => toDartUint16List(toExternRef); } extension Uint16ListToJSInt16Array on Uint16List { @@ -163,7 +160,7 @@ /// [JSInt32Array] <-> [Int32List] extension JSInt32ArrayToInt32List on JSInt32Array { @patch - Int32List get toDart => toDartInt32List(_ref<JSInt32Array>(this)); + Int32List get toDart => toDartInt32List(toExternRef); } extension Int32ListToJSInt32Array on Int32List { @@ -175,7 +172,7 @@ /// [JSUint32Array] <-> [Uint32List] extension JSUint32ArrayToUint32List on JSUint32Array { @patch - Uint32List get toDart => toDartUint32List(_ref<JSUint32Array>(this)); + Uint32List get toDart => toDartUint32List(toExternRef); } extension Uint32ListToJSUint32Array on Uint32List { @@ -187,7 +184,7 @@ /// [JSFloat32Array] <-> [Float32List] extension JSFloat32ArrayToFloat32List on JSFloat32Array { @patch - Float32List get toDart => toDartFloat32List(_ref<JSFloat32Array>(this)); + Float32List get toDart => toDartFloat32List(toExternRef); } extension Float32ListToJSFloat32Array on Float32List { @@ -199,7 +196,7 @@ /// [JSFloat64Array] <-> [Float64List] extension JSFloat64ArrayToFloat64List on JSFloat64Array { @patch - Float64List get toDart => toDartFloat64List(_ref<JSFloat64Array>(this)); + Float64List get toDart => toDartFloat64List(toExternRef); } extension Float64ListToJSFloat64Array on Float64List { @@ -211,7 +208,7 @@ /// [JSArray] <-> [List] extension JSArrayToList on JSArray { @patch - List<JSAny?> get toDart => toDartListJSAny(_ref<JSArray>(this)); + List<JSAny?> get toDart => toDartListJSAny(toExternRef); } extension ListToJSArray on List<JSAny?> { @@ -222,7 +219,7 @@ /// [JSNumber] <-> [double] extension JSNumberToDouble on JSNumber { @patch - double get toDart => toDartNumber(_ref<JSNumber>(this)); + double get toDart => toDartNumber(toExternRef); } extension DoubleToJSNumber on double { @@ -233,7 +230,7 @@ /// [JSBoolean] <-> [bool] extension JSBooleanToBool on JSBoolean { @patch - bool get toDart => toDartBool(_ref<JSBoolean>(this)); + bool get toDart => toDartBool(toExternRef); } extension BoolToJSBoolean on bool { @@ -244,7 +241,7 @@ /// [JSString] <-> [String] extension JSStringToString on JSString { @patch - String get toDart => jsStringToDartString(_ref<JSString>(this)); + String get toDart => jsStringToDartString(toExternRef); } extension StringToJSString on String {
diff --git a/sdk/lib/_internal/wasm/lib/js_util_patch.dart b/sdk/lib/_internal/wasm/lib/js_util_patch.dart index 6a58c56..d98b1ad 100644 --- a/sdk/lib/_internal/wasm/lib/js_util_patch.dart +++ b/sdk/lib/_internal/wasm/lib/js_util_patch.dart
@@ -4,7 +4,6 @@ library dart.js_util; -import "dart:_js_annotations" as js; import "dart:_internal"; import "dart:_js_helper"; import "dart:_js_types"; @@ -45,8 +44,8 @@ convertedObjects[o] = convertedMap; for (final key in o.keys) { final convertedKey = convert(key) as JSValue?; - setPropertyRaw(convertedMap.toExternRef(), convertedKey?.toExternRef(), - (convert(o[key]) as JSValue?)?.toExternRef()); + setPropertyRaw(convertedMap.toExternRef, convertedKey?.toExternRef, + (convert(o[key]) as JSValue?)?.toExternRef); } return convertedMap; } else if (o is Iterable<Object?>) { @@ -66,38 +65,37 @@ } @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, Object name) => - hasPropertyRaw(jsifyRaw(o)!, jsifyRaw(name)!); + hasPropertyRaw(jsifyRaw(o), jsifyRaw(name)); @patch T getProperty<T>(Object o, Object name) => - dartifyRaw(getPropertyRaw(jsifyRaw(o)!, jsifyRaw(name)!)) as T; + dartifyRaw(getPropertyRaw(jsifyRaw(o), jsifyRaw(name))) as T; @patch T setProperty<T>(Object o, Object name, T? value) => - dartifyRaw(setPropertyRaw(jsifyRaw(o)!, jsifyRaw(name)!, jsifyRaw(value))) + dartifyRaw(setPropertyRaw(jsifyRaw(o), jsifyRaw(name), jsifyRaw(value))) as T; @patch -T callMethod<T>(Object o, String method, List<Object?> args) => - dartifyRaw(callMethodVarArgsRaw( - jsifyRaw(o)!, jsifyRaw(method)!, args.toJS().toExternRef())) as T; +T callMethod<T>(Object o, String method, List<Object?> args) => dartifyRaw( + callMethodVarArgsRaw(jsifyRaw(o), jsifyRaw(method), jsifyRaw(args))) as T; @patch bool instanceof(Object? o, Object type) => JS<bool>("(o, t) => o instanceof t", jsifyRaw(o), jsifyRaw(type)); @patch -T callConstructor<T>(Object o, List<Object?> args) => dartifyRaw( - callConstructorVarArgsRaw(jsifyRaw(o)!, args.toJS().toExternRef()))! as T; +T callConstructor<T>(Object o, List<Object?> args) => + dartifyRaw(callConstructorVarArgsRaw(jsifyRaw(o), jsifyRaw(args))) as T; @patch T add<T>(Object? first, Object? second) => throw 'unimplemented'; @@ -169,7 +167,7 @@ return completer.completeError(e); }); - promiseThen(jsifyRaw(jsPromise)!, jsifyRaw(success)!, jsifyRaw(error)!); + promiseThen(jsifyRaw(jsPromise), jsifyRaw(success), jsifyRaw(error)); return completer.future; } @@ -207,7 +205,7 @@ return o; } - WasmExternRef? ref = o.toExternRef(); + WasmExternRef? ref = o.toExternRef; if (ref.isNull || isJSBoolean(ref) || isJSNumber(ref) || @@ -240,8 +238,8 @@ for (int i = 0; i < keys.length; i++) { final key = keys[i]; if (key != null) { - dartMap[key] = convert( - JSValue.box(getPropertyRaw(ref, (key as String).toExternRef()))); + dartMap[key] = + convert(JSValue.box(getPropertyRaw(ref, jsifyRaw(key)))); } } return dartMap;
diff --git a/sdk/lib/_internal/wasm/lib/regexp_helper.dart b/sdk/lib/_internal/wasm/lib/regexp_helper.dart index 45085e4..2afc7a6 100644 --- a/sdk/lib/_internal/wasm/lib/regexp_helper.dart +++ b/sdk/lib/_internal/wasm/lib/regexp_helper.dart
@@ -29,8 +29,8 @@ } extension JSNativeMatchExtension on JSNativeMatch { - external String get input; - external int get index; + external JSString get input; + external JSNumber get index; external JSObject? get groups; } @@ -39,14 +39,14 @@ class JSNativeRegExp {} extension JSNativeRegExpExtension on JSNativeRegExp { - external JSNativeMatch? exec(String string); - external bool test(String string); - external String get flags; - external bool get multiline; - external bool get ignoreCase; - external bool get unicode; - external bool get dotAll; - external set lastIndex(int start); + external JSNativeMatch? exec(JSString string); + external JSBoolean test(JSString string); + external JSString get flags; + external JSBoolean get multiline; + external JSBoolean get ignoreCase; + external JSBoolean get unicode; + external JSBoolean get dotAll; + external set lastIndex(JSNumber start); } class JSSyntaxRegExp implements RegExp { @@ -55,7 +55,7 @@ JSNativeRegExp? _nativeGlobalRegExp; JSNativeRegExp? _nativeAnchoredRegExp; - String toString() => 'RegExp/$pattern/' + _nativeRegExp.flags; + String toString() => 'RegExp/$pattern/' + _nativeRegExp.flags.toDart; JSSyntaxRegExp(String source, {bool multiLine = false, @@ -83,10 +83,10 @@ '$pattern|()', isMultiLine, isCaseSensitive, isUnicode, isDotAll, true); } - bool get isMultiLine => _nativeRegExp.multiline; - bool get isCaseSensitive => !_nativeRegExp.ignoreCase; - bool get isUnicode => _nativeRegExp.unicode; - bool get isDotAll => _nativeRegExp.dotAll; + bool get isMultiLine => _nativeRegExp.multiline.toDart; + bool get isCaseSensitive => !_nativeRegExp.ignoreCase.toDart; + bool get isUnicode => _nativeRegExp.unicode.toDart; + bool get isDotAll => _nativeRegExp.dotAll.toDart; static JSNativeRegExp makeNative(String source, bool multiLine, bool caseSensitive, bool unicode, bool dotAll, bool global) { @@ -104,7 +104,7 @@ } catch (e) { return String(e); } - }""", source.toExternRef(), modifiers.toExternRef()); + }""", source.toExternRef, modifiers.toExternRef); if (isJSRegExp(result)) return JSValue(result!) as JSNativeRegExp; // The returned value is the stringified JavaScript exception. Turn it into // a Dart exception. @@ -113,13 +113,13 @@ } RegExpMatch? firstMatch(String string) { - JSNativeMatch? m = _nativeRegExp.exec(string); + JSNativeMatch? m = _nativeRegExp.exec(string.toJS); if (m.isUndefinedOrNull) return null; return new _MatchImplementation(this, m!); } bool hasMatch(String string) { - return _nativeRegExp.test(string); + return _nativeRegExp.test(string.toJS).toDart; } String? stringMatch(String string) { @@ -137,16 +137,16 @@ RegExpMatch? _execGlobal(String string, int start) { JSNativeRegExp regexp = _nativeGlobalVersion; - regexp.lastIndex = start; - JSNativeMatch? match = regexp.exec(string); + regexp.lastIndex = start.toJS; + JSNativeMatch? match = regexp.exec(string.toJS); if (match.isUndefinedOrNull) return null; return new _MatchImplementation(this, match!); } RegExpMatch? _execAnchored(String string, int start) { JSNativeRegExp regexp = _nativeAnchoredVersion; - regexp.lastIndex = start; - JSNativeMatch? match = regexp.exec(string); + regexp.lastIndex = start.toJS; + JSNativeMatch? match = regexp.exec(string.toJS); if (match.isUndefinedOrNull) return null; // If the last capture group participated, the original regexp did not // match at the start position. @@ -173,22 +173,22 @@ _MatchImplementation(this.pattern, this._match); - String get input => _match.input; + String get input => _match.input.toDart; - int get start => _match.index; + int get start => _match.index.toDart.toInt(); - int get end => (start + (_match[0].toString()).length); + int get end => (start + (_match[0.toJS].toString()).length); String? group(int index) { - if (index < 0 || index >= _match.length) { + if (index < 0 || index >= _match.length.toDart.toInt()) { throw RangeError("Index $index is out of range ${_match.length}"); } - return _match[index]?.toString(); + return _match[index.toJS]?.toString(); } String? operator [](int index) => group(index); - int get groupCount => _match.length - 1; + int get groupCount => _match.length.toDart.toInt() - 1; List<String?> groups(List<int> groups) { List<String?> out = []; @@ -201,10 +201,9 @@ String? namedGroup(String name) { JSObject? groups = _match.groups; if (groups.isDefinedAndNotNull) { - Object? result = groups![name]; + Object? result = dartifyRaw(groups![name.toJS]?.toExternRef); if (result != null || - hasPropertyRaw( - (groups as JSValue).toExternRef(), name.toExternRef())) { + hasPropertyRaw(groups.toExternRef, name.toExternRef)) { return result?.toString(); } }