[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();
       }
     }