[dart2wasm|jscm] Move typed data to JS.

Change-Id: Ic4381818be9fdf3725a7eef8455451447a210b8b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/313281
Commit-Queue: Joshua Litt <joshualitt@google.com>
Reviewed-by: Ömer Ağacan <omersa@google.com>
diff --git a/pkg/dart2wasm/README.md b/pkg/dart2wasm/README.md
index 3223aa4a..26bf072 100644
--- a/pkg/dart2wasm/README.md
+++ b/pkg/dart2wasm/README.md
@@ -39,6 +39,7 @@
 | `--`[`no-`]`print-wasm`                 | no      | Print Wasm instructions of each compiled function.
 | `--`[`no-`]`stringref`                  | no      | Use the experimental stringref Wasm proposal.
 | `--`[`no-`]`enable-asserts`             | no      | Enable assertions at runtime.
+| `--`[`no-`]`js-compatibility`           | no      | Enable JS compatibility mode.
 | `--shared-memory-max-pages` *pagecount* |         | Max size of the imported memory buffer. If `--shared-import-memory` is specified, this must also be specified.
 | `--watch` *offset*                      |         | Print stack trace leading to the byte at offset *offset* in the `.wasm` output file. Can be specified multiple times.
 
diff --git a/pkg/dart2wasm/lib/class_info.dart b/pkg/dart2wasm/lib/class_info.dart
index 63f03d9..7d07b67 100644
--- a/pkg/dart2wasm/lib/class_info.dart
+++ b/pkg/dart2wasm/lib/class_info.dart
@@ -221,7 +221,7 @@
       translator.index.getClass("dart:core", "_ListBase"):
           translator.coreTypes.listClass
     };
-    for (String name in const <String>[
+    for (final name in const <String>[
       "Int8List",
       "Uint8List",
       "Uint8ClampedList",
@@ -247,30 +247,36 @@
 
   late final Set<Class> _neverMasquerades = _computeNeverMasquerades();
 
+  /// These types switch from properly reified non-masquerading types in regular
+  /// Dart2Wasm mode to masquerading types in js compatibility mode.
+  final Set<String> jsCompatibilityTypes = {
+    "JSArrayBufferImpl",
+    "JSArrayBufferViewImpl",
+    "JSDataViewImpl",
+    "JSInt8ArrayImpl",
+    "JSUint8ArrayImpl",
+    "JSUint8ClampedArrayImpl",
+    "JSInt16ArrayImpl",
+    "JSUint16ArrayImpl",
+    "JSInt32ArrayImpl",
+    "JSInt32x4ArrayImpl",
+    "JSUint32ArrayImpl",
+    "JSBigUint64ArrayImpl",
+    "JSBigInt64ArrayImpl",
+    "JSFloat32ArrayImpl",
+    "JSFloat32x4ArrayImpl",
+    "JSFloat64ArrayImpl",
+    "JSFloat64x2ArrayImpl",
+  };
+
   Set<Class> _computeNeverMasquerades() {
-    // The JS types do not masquerade, but they aren't always used so we have to
-    // construct this set programmatically.
+    // The JS types do not masquerade in regular Dart2Wasm, but they aren't
+    // always used so we have to construct this set programmatically.
     final jsTypesLibraryIndex =
         LibraryIndex(translator.component, ["dart:_js_types"]);
     final neverMasquerades = [
-      "JSArrayBufferImpl",
-      "JSArrayBufferViewImpl",
-      "JSDataViewImpl",
       "JSStringImpl",
-      "JSInt8ArrayImpl",
-      "JSUint8ArrayImpl",
-      "JSUint8ClampedArrayImpl",
-      "JSInt16ArrayImpl",
-      "JSUint16ArrayImpl",
-      "JSInt32ArrayImpl",
-      "JSInt32x4ArrayImpl",
-      "JSUint32ArrayImpl",
-      "JSBigUint64ArrayImpl",
-      "JSBigInt64ArrayImpl",
-      "JSFloat32ArrayImpl",
-      "JSFloat32x4ArrayImpl",
-      "JSFloat64ArrayImpl",
-      "JSFloat64x2ArrayImpl",
+      if (!translator.options.jsCompatibility) ...jsCompatibilityTypes,
     ]
         .map((name) => jsTypesLibraryIndex.tryGetClass("dart:_js_types", name))
         .toSet();
diff --git a/pkg/dart2wasm/lib/compile.dart b/pkg/dart2wasm/lib/compile.dart
index 1c6bf96..d1c5ff5 100644
--- a/pkg/dart2wasm/lib/compile.dart
+++ b/pkg/dart2wasm/lib/compile.dart
@@ -32,7 +32,8 @@
 import 'package:dart2wasm/js/runtime_generator.dart' as js;
 import 'package:dart2wasm/record_class_generator.dart';
 import 'package:dart2wasm/records.dart';
-import 'package:dart2wasm/target.dart';
+import 'package:dart2wasm/target.dart' hide Mode;
+import 'package:dart2wasm/target.dart' as wasm show Mode;
 import 'package:dart2wasm/translator.dart';
 
 class CompilerOutput {
@@ -57,8 +58,16 @@
     handleDiagnosticMessage(message);
   }
 
-  final WasmTarget target =
-      WasmTarget(removeAsserts: !options.translatorOptions.enableAsserts);
+  final wasm.Mode mode;
+  if (options.translatorOptions.useStringref) {
+    mode = wasm.Mode.stringref;
+  } else if (options.translatorOptions.jsCompatibility) {
+    mode = wasm.Mode.jsCompatibility;
+  } else {
+    mode = wasm.Mode.regular;
+  }
+  final WasmTarget target = WasmTarget(
+      removeAsserts: !options.translatorOptions.enableAsserts, mode: mode);
   CompilerOptions compilerOptions = CompilerOptions()
     ..target = target
     ..sdkRoot = options.sdkPath
diff --git a/pkg/dart2wasm/lib/dart2wasm.dart b/pkg/dart2wasm/lib/dart2wasm.dart
index 32668d2..fe6a9cf 100644
--- a/pkg/dart2wasm/lib/dart2wasm.dart
+++ b/pkg/dart2wasm/lib/dart2wasm.dart
@@ -36,6 +36,9 @@
       defaultsTo: _d.translatorOptions.printWasm),
   Flag("stringref", (o, value) => o.translatorOptions.useStringref = value,
       defaultsTo: _d.translatorOptions.useStringref),
+  Flag("js-compatibility",
+      (o, value) => o.translatorOptions.jsCompatibility = value,
+      defaultsTo: _d.translatorOptions.jsCompatibility),
   Flag(
       "enable-asserts", (o, value) => o.translatorOptions.enableAsserts = value,
       defaultsTo: _d.translatorOptions.enableAsserts),
diff --git a/pkg/dart2wasm/lib/target.dart b/pkg/dart2wasm/lib/target.dart
index 82d4d52..1de11ee 100644
--- a/pkg/dart2wasm/lib/target.dart
+++ b/pkg/dart2wasm/lib/target.dart
@@ -131,7 +131,8 @@
           uri.path == '_typed_data' ||
           uri.path == '_boxed_double' ||
           uri.path == '_boxed_int' ||
-          uri.path == '_js_types');
+          uri.path == '_js_types' ||
+          uri.path == '_typed_data_helper');
 
   @override
   bool allowPlatformPrivateLibraryAccess(Uri importer, Uri imported) =>
diff --git a/pkg/dart2wasm/lib/translator.dart b/pkg/dart2wasm/lib/translator.dart
index c0d7853..5fb43d8 100644
--- a/pkg/dart2wasm/lib/translator.dart
+++ b/pkg/dart2wasm/lib/translator.dart
@@ -42,6 +42,7 @@
   // If the default value for [useStringref] is changed, also update the
   // `sdk/bin/dart2wasm` script.
   bool useStringref = false;
+  bool jsCompatibility = false;
   int inliningLimit = 0;
   int? sharedMemoryMaxPages;
   List<int>? watchPoints = null;
diff --git a/sdk/lib/_internal/wasm/lib/js_typed_array.dart b/sdk/lib/_internal/wasm/lib/js_typed_array.dart
index 9418e38..850d8bf 100644
--- a/sdk/lib/_internal/wasm/lib/js_typed_array.dart
+++ b/sdk/lib/_internal/wasm/lib/js_typed_array.dart
@@ -46,7 +46,7 @@
     _offsetAlignmentCheck(offsetInBytes, Int32x4List.bytesPerElement);
     length ??= (lengthInBytes - offsetInBytes) ~/ Int32x4List.bytesPerElement;
     final storage = JSInt32ArrayImpl.view(this, offsetInBytes, length * 4);
-    return JSInt32x4ArrayImpl._externalStorage(storage);
+    return JSInt32x4ArrayImpl.externalStorage(storage);
   }
 
   Float32List asFloat32List([int offsetInBytes = 0, int? length]) =>
@@ -59,14 +59,14 @@
     _offsetAlignmentCheck(offsetInBytes, Float32x4List.bytesPerElement);
     length ??= (lengthInBytes - offsetInBytes) ~/ Float32x4List.bytesPerElement;
     final storage = JSFloat32ArrayImpl.view(this, offsetInBytes, length * 4);
-    return JSFloat32x4ArrayImpl._externalStorage(storage);
+    return JSFloat32x4ArrayImpl.externalStorage(storage);
   }
 
   Float64x2List asFloat64x2List([int offsetInBytes = 0, int? length]) {
     _offsetAlignmentCheck(offsetInBytes, Float64x2List.bytesPerElement);
     length ??= (lengthInBytes - offsetInBytes) ~/ Float64x2List.bytesPerElement;
     final storage = JSFloat64ArrayImpl.view(this, offsetInBytes, length * 2);
-    return JSFloat64x2ArrayImpl._externalStorage(storage);
+    return JSFloat64x2ArrayImpl.externalStorage(storage);
   }
 
   ByteData asByteData([int offsetInBytes = 0, int? length]) =>
@@ -485,7 +485,7 @@
     implements Int32x4List {
   final JSInt32ArrayImpl _storage;
 
-  JSInt32x4ArrayImpl._externalStorage(JSInt32ArrayImpl storage)
+  JSInt32x4ArrayImpl.externalStorage(JSInt32ArrayImpl storage)
       : _storage = storage;
 
   @override
@@ -525,7 +525,7 @@
   @override
   Int32x4List sublist(int start, [int? end]) {
     final stop = RangeError.checkValidRange(start, end, length);
-    return JSInt32x4ArrayImpl._externalStorage(
+    return JSInt32x4ArrayImpl.externalStorage(
         _storage.sublist(start * 4, stop * 4) as JSInt32ArrayImpl);
   }
 }
@@ -719,7 +719,7 @@
     implements Float32x4List {
   final JSFloat32ArrayImpl _storage;
 
-  JSFloat32x4ArrayImpl._externalStorage(JSFloat32ArrayImpl storage)
+  JSFloat32x4ArrayImpl.externalStorage(JSFloat32ArrayImpl storage)
       : _storage = storage;
 
   @override
@@ -759,7 +759,7 @@
   @override
   Float32x4List sublist(int start, [int? end]) {
     final stop = RangeError.checkValidRange(start, end, length);
-    return JSFloat32x4ArrayImpl._externalStorage(
+    return JSFloat32x4ArrayImpl.externalStorage(
         _storage.sublist(start * 4, stop * 4) as JSFloat32ArrayImpl);
   }
 }
@@ -769,7 +769,7 @@
     implements Float64x2List {
   final JSFloat64ArrayImpl _storage;
 
-  JSFloat64x2ArrayImpl._externalStorage(JSFloat64ArrayImpl storage)
+  JSFloat64x2ArrayImpl.externalStorage(JSFloat64ArrayImpl storage)
       : _storage = storage;
 
   @override
@@ -805,7 +805,7 @@
   @override
   Float64x2List sublist(int start, [int? end]) {
     final stop = RangeError.checkValidRange(start, end, length);
-    return JSFloat64x2ArrayImpl._externalStorage(
+    return JSFloat64x2ArrayImpl.externalStorage(
         _storage.sublist(start * 2, stop * 2) as JSFloat64ArrayImpl);
   }
 }
diff --git a/sdk/lib/_internal/wasm_js_compatibility/lib/typed_data_helper.dart b/sdk/lib/_internal/wasm_js_compatibility/lib/typed_data_helper.dart
new file mode 100644
index 0000000..e6c49a0
--- /dev/null
+++ b/sdk/lib/_internal/wasm_js_compatibility/lib/typed_data_helper.dart
@@ -0,0 +1,378 @@
+// Copyright (c) 2023, 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.
+
+library dart._typed_data_helper;
+
+import 'dart:_internal' show UnmodifiableListBase;
+import 'dart:_js_helper' as js;
+import 'dart:_js_types';
+import 'dart:_string_helper';
+import 'dart:_wasm';
+import 'dart:typed_data';
+
+/// A read-only view of a [ByteBuffer].
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableByteBufferView.
+final class UnmodifiableByteBufferViewImpl
+    implements ByteBuffer, UnmodifiableByteBufferView {
+  final ByteBuffer _data;
+
+  UnmodifiableByteBufferViewImpl(ByteBuffer data) : _data = data;
+
+  int get lengthInBytes => _data.lengthInBytes;
+
+  Uint8List asUint8List([int offsetInBytes = 0, int? length]) =>
+      UnmodifiableUint8ListView(_data.asUint8List(offsetInBytes, length));
+
+  Int8List asInt8List([int offsetInBytes = 0, int? length]) =>
+      UnmodifiableInt8ListView(_data.asInt8List(offsetInBytes, length));
+
+  Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int? length]) =>
+      UnmodifiableUint8ClampedListView(
+          _data.asUint8ClampedList(offsetInBytes, length));
+
+  Uint16List asUint16List([int offsetInBytes = 0, int? length]) =>
+      UnmodifiableUint16ListView(_data.asUint16List(offsetInBytes, length));
+
+  Int16List asInt16List([int offsetInBytes = 0, int? length]) =>
+      UnmodifiableInt16ListView(_data.asInt16List(offsetInBytes, length));
+
+  Uint32List asUint32List([int offsetInBytes = 0, int? length]) =>
+      UnmodifiableUint32ListView(_data.asUint32List(offsetInBytes, length));
+
+  Int32List asInt32List([int offsetInBytes = 0, int? length]) =>
+      UnmodifiableInt32ListView(_data.asInt32List(offsetInBytes, length));
+
+  Uint64List asUint64List([int offsetInBytes = 0, int? length]) =>
+      UnmodifiableUint64ListView(_data.asUint64List(offsetInBytes, length));
+
+  Int64List asInt64List([int offsetInBytes = 0, int? length]) =>
+      UnmodifiableInt64ListView(_data.asInt64List(offsetInBytes, length));
+
+  Int32x4List asInt32x4List([int offsetInBytes = 0, int? length]) =>
+      UnmodifiableInt32x4ListView(_data.asInt32x4List(offsetInBytes, length));
+
+  Float32List asFloat32List([int offsetInBytes = 0, int? length]) =>
+      UnmodifiableFloat32ListView(_data.asFloat32List(offsetInBytes, length));
+
+  Float64List asFloat64List([int offsetInBytes = 0, int? length]) =>
+      UnmodifiableFloat64ListView(_data.asFloat64List(offsetInBytes, length));
+
+  Float32x4List asFloat32x4List([int offsetInBytes = 0, int? length]) =>
+      UnmodifiableFloat32x4ListView(
+          _data.asFloat32x4List(offsetInBytes, length));
+
+  Float64x2List asFloat64x2List([int offsetInBytes = 0, int? length]) =>
+      UnmodifiableFloat64x2ListView(
+          _data.asFloat64x2List(offsetInBytes, length));
+
+  ByteData asByteData([int offsetInBytes = 0, int? length]) =>
+      UnmodifiableByteDataView(_data.asByteData(offsetInBytes, length));
+}
+
+/// A read-only view of a [ByteData].
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableByteDataView.
+final class UnmodifiableByteDataViewImpl
+    implements ByteData, UnmodifiableByteDataView {
+  final ByteData _data;
+
+  UnmodifiableByteDataViewImpl(ByteData data) : _data = data;
+
+  int getInt8(int byteOffset) => _data.getInt8(byteOffset);
+
+  void setInt8(int byteOffset, int value) => _unsupported();
+
+  int getUint8(int byteOffset) => _data.getUint8(byteOffset);
+
+  void setUint8(int byteOffset, int value) => _unsupported();
+
+  int getInt16(int byteOffset, [Endian endian = Endian.big]) =>
+      _data.getInt16(byteOffset, endian);
+
+  void setInt16(int byteOffset, int value, [Endian endian = Endian.big]) =>
+      _unsupported();
+
+  int getUint16(int byteOffset, [Endian endian = Endian.big]) =>
+      _data.getUint16(byteOffset, endian);
+
+  void setUint16(int byteOffset, int value, [Endian endian = Endian.big]) =>
+      _unsupported();
+
+  int getInt32(int byteOffset, [Endian endian = Endian.big]) =>
+      _data.getInt32(byteOffset, endian);
+
+  void setInt32(int byteOffset, int value, [Endian endian = Endian.big]) =>
+      _unsupported();
+
+  int getUint32(int byteOffset, [Endian endian = Endian.big]) =>
+      _data.getUint32(byteOffset, endian);
+
+  void setUint32(int byteOffset, int value, [Endian endian = Endian.big]) =>
+      _unsupported();
+
+  int getInt64(int byteOffset, [Endian endian = Endian.big]) =>
+      _data.getInt64(byteOffset, endian);
+
+  void setInt64(int byteOffset, int value, [Endian endian = Endian.big]) =>
+      _unsupported();
+
+  int getUint64(int byteOffset, [Endian endian = Endian.big]) =>
+      _data.getUint64(byteOffset, endian);
+
+  void setUint64(int byteOffset, int value, [Endian endian = Endian.big]) =>
+      _unsupported();
+
+  double getFloat32(int byteOffset, [Endian endian = Endian.big]) =>
+      _data.getFloat32(byteOffset, endian);
+
+  void setFloat32(int byteOffset, double value, [Endian endian = Endian.big]) =>
+      _unsupported();
+
+  double getFloat64(int byteOffset, [Endian endian = Endian.big]) =>
+      _data.getFloat64(byteOffset, endian);
+
+  void setFloat64(int byteOffset, double value, [Endian endian = Endian.big]) =>
+      _unsupported();
+
+  int get elementSizeInBytes => _data.elementSizeInBytes;
+
+  int get offsetInBytes => _data.offsetInBytes;
+
+  int get lengthInBytes => _data.lengthInBytes;
+
+  ByteBuffer get buffer => UnmodifiableByteBufferView(_data.buffer);
+
+  void _unsupported() =>
+      throw UnsupportedError("An UnmodifiableByteDataView may not be modified");
+}
+
+mixin UnmodifiableListMixin<N, L extends List<N>, TD extends TypedData> {
+  L get _list;
+  TD get _data => (_list as TD);
+
+  int get length => _list.length;
+
+  N operator [](int index) => _list[index];
+
+  int get elementSizeInBytes => _data.elementSizeInBytes;
+
+  int get offsetInBytes => _data.offsetInBytes;
+
+  int get lengthInBytes => _data.lengthInBytes;
+
+  ByteBuffer get buffer => UnmodifiableByteBufferView(_data.buffer);
+
+  L createList(int length);
+
+  L sublist(int start, [int? end]) {
+    int endIndex = RangeError.checkValidRange(start, end, length);
+    int sublistLength = endIndex - start;
+    L result = createList(sublistLength);
+    result.setRange(0, sublistLength, _list, start);
+    return result;
+  }
+}
+
+/// View of a [Uint8List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableUint8ListView.
+final class UnmodifiableUint8ListViewImpl extends UnmodifiableListBase<int>
+    with UnmodifiableListMixin<int, Uint8List, Uint8List>
+    implements UnmodifiableUint8ListView {
+  final Uint8List _list;
+  UnmodifiableUint8ListViewImpl(Uint8List list) : _list = list;
+
+  @override
+  Uint8List createList(int length) => Uint8List(length);
+}
+
+/// View of a [Int8List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableInt8ListView.
+final class UnmodifiableInt8ListViewImpl extends UnmodifiableListBase<int>
+    with UnmodifiableListMixin<int, Int8List, Int8List>
+    implements UnmodifiableInt8ListView {
+  final Int8List _list;
+  UnmodifiableInt8ListViewImpl(Int8List list) : _list = list;
+
+  @override
+  Int8List createList(int length) => Int8List(length);
+}
+
+/// View of a [Uint8ClampedList] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableUint8ClampedListView.
+final class UnmodifiableUint8ClampedListViewImpl
+    extends UnmodifiableListBase<int>
+    with UnmodifiableListMixin<int, Uint8ClampedList, Uint8ClampedList>
+    implements UnmodifiableUint8ClampedListView {
+  final Uint8ClampedList _list;
+  UnmodifiableUint8ClampedListViewImpl(Uint8ClampedList list) : _list = list;
+
+  @override
+  Uint8ClampedList createList(int length) => Uint8ClampedList(length);
+}
+
+/// View of a [Uint16List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableUint16ListView.
+final class UnmodifiableUint16ListViewImpl extends UnmodifiableListBase<int>
+    with UnmodifiableListMixin<int, Uint16List, Uint16List>
+    implements UnmodifiableUint16ListView {
+  final Uint16List _list;
+  UnmodifiableUint16ListViewImpl(Uint16List list) : _list = list;
+
+  @override
+  Uint16List createList(int length) => Uint16List(length);
+}
+
+/// View of a [Int16List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableInt16ListView.
+final class UnmodifiableInt16ListViewImpl extends UnmodifiableListBase<int>
+    with UnmodifiableListMixin<int, Int16List, Int16List>
+    implements UnmodifiableInt16ListView {
+  final Int16List _list;
+  UnmodifiableInt16ListViewImpl(Int16List list) : _list = list;
+
+  @override
+  Int16List createList(int length) => Int16List(length);
+}
+
+/// View of a [Uint32List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableUint32ListView.
+final class UnmodifiableUint32ListViewImpl extends UnmodifiableListBase<int>
+    with UnmodifiableListMixin<int, Uint32List, Uint32List>
+    implements UnmodifiableUint32ListView {
+  final Uint32List _list;
+  UnmodifiableUint32ListViewImpl(Uint32List list) : _list = list;
+
+  @override
+  Uint32List createList(int length) => Uint32List(length);
+}
+
+/// View of a [Int32List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableInt32ListView.
+final class UnmodifiableInt32ListViewImpl extends UnmodifiableListBase<int>
+    with UnmodifiableListMixin<int, Int32List, Int32List>
+    implements UnmodifiableInt32ListView {
+  final Int32List _list;
+  UnmodifiableInt32ListViewImpl(Int32List list) : _list = list;
+
+  @override
+  Int32List createList(int length) => Int32List(length);
+}
+
+/// View of a [Uint64List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableUint64ListView.
+final class UnmodifiableUint64ListViewImpl extends UnmodifiableListBase<int>
+    with UnmodifiableListMixin<int, Uint64List, Uint64List>
+    implements UnmodifiableUint64ListView {
+  final Uint64List _list;
+  UnmodifiableUint64ListViewImpl(Uint64List list) : _list = list;
+
+  @override
+  Uint64List createList(int length) => Uint64List(length);
+}
+
+/// View of a [Int64List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableInt64ListView.
+final class UnmodifiableInt64ListViewImpl extends UnmodifiableListBase<int>
+    with UnmodifiableListMixin<int, Int64List, Int64List>
+    implements UnmodifiableInt64ListView {
+  final Int64List _list;
+  UnmodifiableInt64ListViewImpl(Int64List list) : _list = list;
+
+  @override
+  Int64List createList(int length) => Int64List(length);
+}
+
+/// View of a [Int32x4List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableInt32x4ListView.
+final class UnmodifiableInt32x4ListViewImpl
+    extends UnmodifiableListBase<Int32x4>
+    with UnmodifiableListMixin<Int32x4, Int32x4List, Int32x4List>
+    implements UnmodifiableInt32x4ListView {
+  final Int32x4List _list;
+  UnmodifiableInt32x4ListViewImpl(Int32x4List list) : _list = list;
+
+  @override
+  Int32x4List createList(int length) => Int32x4List(length);
+}
+
+/// View of a [Float32x4List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableFloat32x4ListView.
+final class UnmodifiableFloat32x4ListViewImpl
+    extends UnmodifiableListBase<Float32x4>
+    with UnmodifiableListMixin<Float32x4, Float32x4List, Float32x4List>
+    implements UnmodifiableFloat32x4ListView {
+  final Float32x4List _list;
+  UnmodifiableFloat32x4ListViewImpl(Float32x4List list) : _list = list;
+
+  @override
+  Float32x4List createList(int length) => Float32x4List(length);
+}
+
+/// View of a [Float64x2List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableFloat64x2ListView.
+final class UnmodifiableFloat64x2ListViewImpl
+    extends UnmodifiableListBase<Float64x2>
+    with UnmodifiableListMixin<Float64x2, Float64x2List, Float64x2List>
+    implements UnmodifiableFloat64x2ListView {
+  final Float64x2List _list;
+  UnmodifiableFloat64x2ListViewImpl(Float64x2List list) : _list = list;
+
+  @override
+  Float64x2List createList(int length) => Float64x2List(length);
+}
+
+/// View of a [Float32List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableFloat32ListView.
+final class UnmodifiableFloat32ListViewImpl extends UnmodifiableListBase<double>
+    with UnmodifiableListMixin<double, Float32List, Float32List>
+    implements UnmodifiableFloat32ListView {
+  final Float32List _list;
+  UnmodifiableFloat32ListViewImpl(Float32List list) : _list = list;
+
+  @override
+  Float32List createList(int length) => Float32List(length);
+}
+
+/// View of a [Float64List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableFloat64ListView.
+final class UnmodifiableFloat64ListViewImpl extends UnmodifiableListBase<double>
+    with UnmodifiableListMixin<double, Float64List, Float64List>
+    implements UnmodifiableFloat64ListView {
+  final Float64List _list;
+  UnmodifiableFloat64ListViewImpl(Float64List list) : _list = list;
+
+  @override
+  Float64List createList(int length) => Float64List(length);
+}
diff --git a/sdk/lib/_internal/wasm_js_compatibility/lib/typed_data_patch.dart b/sdk/lib/_internal/wasm_js_compatibility/lib/typed_data_patch.dart
new file mode 100644
index 0000000..b8ac031
--- /dev/null
+++ b/sdk/lib/_internal/wasm_js_compatibility/lib/typed_data_patch.dart
@@ -0,0 +1,340 @@
+// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:_internal' show FixedLengthListMixin, patch, UnmodifiableListBase;
+import 'dart:_js_helper' as js;
+import 'dart:_js_types';
+import 'dart:_simd';
+import 'dart:_string_helper';
+import 'dart:_typed_data_helper';
+import 'dart:_wasm';
+import 'dart:typed_data';
+import 'dart:js_interop';
+
+// TODO(joshualitt): Optimizations for this file:
+//   * Move list to JS and allocate on the JS side for `fromLength`
+//     constructors.
+
+@patch
+class ByteData {
+  @patch
+  factory ByteData(int length) {
+    return JSDataViewImpl(js.JS<WasmExternRef?>(
+        'l => new DataView(new ArrayBuffer(l))', length.toDouble()));
+  }
+}
+
+@patch
+class Uint8List {
+  @patch
+  factory Uint8List(int length) {
+    return JSUint8ArrayImpl(
+        js.JS<WasmExternRef?>('l => new Uint8Array(l)', length.toDouble()));
+  }
+
+  @patch
+  factory Uint8List.fromList(List<int> elements) =>
+      Uint8List(elements.length)..setRange(0, elements.length, elements);
+}
+
+@patch
+class Int8List {
+  @patch
+  factory Int8List(int length) {
+    return JSInt8ArrayImpl(
+        js.JS<WasmExternRef?>('l => new Int8Array(l)', length.toDouble()));
+  }
+
+  @patch
+  factory Int8List.fromList(List<int> elements) =>
+      Int8List(elements.length)..setRange(0, elements.length, elements);
+}
+
+@patch
+class Uint8ClampedList {
+  @patch
+  factory Uint8ClampedList(int length) {
+    return JSUint8ClampedArrayImpl(js.JS<WasmExternRef?>(
+        'l => new Uint8ClampedArray(l)', length.toDouble()));
+  }
+
+  @patch
+  factory Uint8ClampedList.fromList(List<int> elements) =>
+      Uint8ClampedList(elements.length)..setRange(0, elements.length, elements);
+}
+
+@patch
+class Uint16List {
+  @patch
+  factory Uint16List(int length) {
+    return JSUint16ArrayImpl(
+        js.JS<WasmExternRef?>('l => new Uint16Array(l)', length.toDouble()));
+  }
+
+  @patch
+  factory Uint16List.fromList(List<int> elements) =>
+      Uint16List(elements.length)..setRange(0, elements.length, elements);
+}
+
+@patch
+class Int16List {
+  @patch
+  factory Int16List(int length) {
+    return JSInt16ArrayImpl(
+        js.JS<WasmExternRef?>('l => new Int16Array(l)', length.toDouble()));
+  }
+
+  @patch
+  factory Int16List.fromList(List<int> elements) =>
+      Int16List(elements.length)..setRange(0, elements.length, elements);
+}
+
+@patch
+class Uint32List {
+  @patch
+  factory Uint32List(int length) {
+    return JSUint32ArrayImpl(
+        js.JS<WasmExternRef?>('l => new Uint32Array(l)', length.toDouble()));
+  }
+
+  @patch
+  factory Uint32List.fromList(List<int> elements) =>
+      Uint32List(elements.length)..setRange(0, elements.length, elements);
+}
+
+@patch
+class Int32List {
+  @patch
+  factory Int32List(int length) {
+    return JSInt32ArrayImpl(
+        js.JS<WasmExternRef?>('l => new Int32Array(l)', length.toDouble()));
+  }
+
+  @patch
+  factory Int32List.fromList(List<int> elements) =>
+      Int32List(elements.length)..setRange(0, elements.length, elements);
+}
+
+@patch
+class Int32x4List {
+  @patch
+  factory Int32x4List(int length) {
+    return JSInt32x4ArrayImpl.externalStorage(JSInt32ArrayImpl(js
+        .JS<WasmExternRef?>('l => new Int32Array(l * 4)', length.toDouble())));
+  }
+
+  @patch
+  factory Int32x4List.fromList(List<Int32x4> elements) {
+    final length = elements.length;
+    final l = Int32x4List(length);
+    for (var i = 0; i < length; i++) {
+      l[i] = elements[i];
+    }
+    return l;
+  }
+}
+
+@patch
+class Int64List {
+  @patch
+  factory Int64List(int length) {
+    return JSBigInt64ArrayImpl(
+        js.JS<WasmExternRef?>('l => new BigInt64Array(l)', length.toDouble()));
+  }
+
+  @patch
+  factory Int64List.fromList(List<int> elements) =>
+      Int64List(elements.length)..setRange(0, elements.length, elements);
+}
+
+@patch
+class Uint64List {
+  @patch
+  factory Uint64List(int length) {
+    return JSBigUint64ArrayImpl(
+        js.JS<WasmExternRef?>('l => new BigUint64Array(l)', length.toDouble()));
+  }
+
+  @patch
+  factory Uint64List.fromList(List<int> elements) =>
+      Uint64List(elements.length)..setRange(0, elements.length, elements);
+}
+
+@patch
+class Float32List {
+  @patch
+  factory Float32List(int length) {
+    return JSFloat32ArrayImpl(
+        js.JS<WasmExternRef?>('l => new Float32Array(l)', length.toDouble()));
+  }
+
+  @patch
+  factory Float32List.fromList(List<double> elements) =>
+      Float32List(elements.length)..setRange(0, elements.length, elements);
+}
+
+@patch
+class Float32x4List {
+  @patch
+  factory Float32x4List(int length) {
+    return JSFloat32x4ArrayImpl.externalStorage(JSFloat32ArrayImpl(
+        js.JS<WasmExternRef?>(
+            'l => new Float32Array(l * 4)', length.toDouble())));
+  }
+
+  @patch
+  factory Float32x4List.fromList(List<Float32x4> elements) {
+    final length = elements.length;
+    final l = Float32x4List(length);
+    for (var i = 0; i < length; i++) {
+      l[i] = elements[i];
+    }
+    return l;
+  }
+}
+
+@patch
+class Float64List {
+  @patch
+  factory Float64List(int length) {
+    return JSFloat64ArrayImpl(
+        js.JS<WasmExternRef?>('l => new Float64Array(l)', length.toDouble()));
+  }
+
+  @patch
+  factory Float64List.fromList(List<double> elements) =>
+      Float64List(elements.length)..setRange(0, elements.length, elements);
+}
+
+@patch
+class Float64x2List {
+  @patch
+  factory Float64x2List(int length) {
+    return JSFloat64x2ArrayImpl.externalStorage(JSFloat64ArrayImpl(
+        js.JS<WasmExternRef?>(
+            'l => new Float64Array(l * 2)', length.toDouble())));
+  }
+
+  @patch
+  factory Float64x2List.fromList(List<Float64x2> elements) {
+    final length = elements.length;
+    final l = Float64x2List(length);
+    for (var i = 0; i < length; i++) {
+      l[i] = elements[i];
+    }
+    return l;
+  }
+}
+
+@patch
+abstract class UnmodifiableByteBufferView implements Uint8List {
+  @patch
+  factory UnmodifiableByteBufferView(ByteBuffer data) =
+      UnmodifiableByteBufferViewImpl;
+}
+
+@patch
+abstract class UnmodifiableByteDataView implements Uint8List {
+  @patch
+  factory UnmodifiableByteDataView(ByteData data) =
+      UnmodifiableByteDataViewImpl;
+}
+
+@patch
+abstract class UnmodifiableUint8ListView implements Uint8List {
+  @patch
+  factory UnmodifiableUint8ListView(Uint8List list) =
+      UnmodifiableUint8ListViewImpl;
+}
+
+@patch
+abstract class UnmodifiableInt8ListView implements Int8List {
+  @patch
+  factory UnmodifiableInt8ListView(Int8List list) =
+      UnmodifiableInt8ListViewImpl;
+}
+
+@patch
+abstract class UnmodifiableUint8ClampedListView implements Uint8ClampedList {
+  @patch
+  factory UnmodifiableUint8ClampedListView(Uint8ClampedList list) =
+      UnmodifiableUint8ClampedListViewImpl;
+}
+
+@patch
+abstract class UnmodifiableUint16ListView implements Uint16List {
+  @patch
+  factory UnmodifiableUint16ListView(Uint16List list) =
+      UnmodifiableUint16ListViewImpl;
+}
+
+@patch
+abstract class UnmodifiableInt16ListView implements Int16List {
+  @patch
+  factory UnmodifiableInt16ListView(Int16List list) =
+      UnmodifiableInt16ListViewImpl;
+}
+
+@patch
+abstract class UnmodifiableUint32ListView implements Uint32List {
+  @patch
+  factory UnmodifiableUint32ListView(Uint32List list) =
+      UnmodifiableUint32ListViewImpl;
+}
+
+@patch
+abstract class UnmodifiableInt32ListView implements Int32List {
+  @patch
+  factory UnmodifiableInt32ListView(Int32List list) =
+      UnmodifiableInt32ListViewImpl;
+}
+
+@patch
+abstract class UnmodifiableUint64ListView implements Uint64List {
+  @patch
+  factory UnmodifiableUint64ListView(Uint64List list) =
+      UnmodifiableUint64ListViewImpl;
+}
+
+@patch
+abstract class UnmodifiableInt64ListView implements Int64List {
+  @patch
+  factory UnmodifiableInt64ListView(Int64List list) =
+      UnmodifiableInt64ListViewImpl;
+}
+
+@patch
+abstract class UnmodifiableInt32x4ListView implements Int32x4List {
+  @patch
+  factory UnmodifiableInt32x4ListView(Int32x4List list) =
+      UnmodifiableInt32x4ListViewImpl;
+}
+
+@patch
+abstract class UnmodifiableFloat32x4ListView implements Float32x4List {
+  @patch
+  factory UnmodifiableFloat32x4ListView(Float32x4List list) =
+      UnmodifiableFloat32x4ListViewImpl;
+}
+
+@patch
+abstract class UnmodifiableFloat64x2ListView implements Float64x2List {
+  @patch
+  factory UnmodifiableFloat64x2ListView(Float64x2List list) =
+      UnmodifiableFloat64x2ListViewImpl;
+}
+
+@patch
+abstract class UnmodifiableFloat32ListView implements Float32List {
+  @patch
+  factory UnmodifiableFloat32ListView(Float32List list) =
+      UnmodifiableFloat32ListViewImpl;
+}
+
+@patch
+abstract class UnmodifiableFloat64ListView implements Float64List {
+  @patch
+  factory UnmodifiableFloat64ListView(Float64List list) =
+      UnmodifiableFloat64ListViewImpl;
+}
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index d62a84c..92c8309 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -122,7 +122,7 @@
   "wasm": {
     "include": [
       {
-        "target": "wasm_common"
+        "target": "wasm_base"
       }
     ],
     "libraries": {
@@ -150,7 +150,7 @@
   "wasm_stringref": {
     "include": [
       {
-        "target": "wasm_common"
+        "target": "wasm_base"
       }
     ],
     "libraries": {
@@ -182,6 +182,9 @@
       }
     ],
     "libraries": {
+      "_typed_data_helper": {
+        "uri": "_internal/wasm_js_compatibility/lib/typed_data_helper.dart"
+      },
       "core": {
         "uri": "core/core.dart",
         "patches": [
@@ -200,6 +203,13 @@
           "_internal/wasm/lib/sync_star_patch.dart",
           "_internal/wasm/lib/weak_patch.dart"
         ]
+      },
+      "typed_data": {
+        "uri": "typed_data/typed_data.dart",
+        "patches": [
+          "_internal/wasm_js_compatibility/lib/typed_data_patch.dart",
+          "_internal/wasm/lib/simd_patch.dart"
+        ]
       }
     }
   },
@@ -220,9 +230,6 @@
       "_simd": {
         "uri": "_internal/wasm/lib/simd.dart"
       },
-      "_typed_data": {
-        "uri": "_internal/wasm/lib/typed_data.dart"
-      },
       "_internal": {
         "uri": "internal/internal.dart",
         "patches": [
@@ -317,6 +324,18 @@
       "math": {
         "uri": "math/math.dart",
         "patches": "_internal/wasm/lib/math_patch.dart"
+      }
+    }
+  },
+  "wasm_base": {
+    "include": [
+      {
+        "target": "wasm_common"
+      }
+    ],
+    "libraries": {
+      "_typed_data": {
+        "uri": "_internal/wasm/lib/typed_data.dart"
       },
       "typed_data": {
         "uri": "typed_data/typed_data.dart",
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index 43af091..b8fefd9 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -114,7 +114,7 @@
 
 wasm:
   include:
-    - target: "wasm_common"
+    - target: "wasm_base"
   libraries:
     core:
       uri: core/core.dart
@@ -136,7 +136,7 @@
 
 wasm_stringref:
   include:
-    - target: "wasm_common"
+    - target: "wasm_base"
   libraries:
     core:
       uri: core/core.dart
@@ -160,23 +160,30 @@
   include:
     - target: "wasm_common"
   libraries:
+    _typed_data_helper:
+      uri: _internal/wasm_js_compatibility/lib/typed_data_helper.dart
     core:
       uri: core/core.dart
       patches:
-      - _internal/wasm/lib/core_patch.dart
-      - _internal/vm_shared/lib/array_patch.dart
-      - _internal/vm_shared/lib/bigint_patch.dart
-      - _internal/vm_shared/lib/bool_patch.dart
-      - _internal/vm_shared/lib/date_patch.dart
-      - _internal/vm_shared/lib/integers_patch.dart
-      - _internal/vm_shared/lib/map_patch.dart
-      - _internal/vm_shared/lib/null_patch.dart
-      - _internal/vm_shared/lib/string_buffer_patch.dart
-      - _internal/wasm/lib/date_patch_patch.dart
-      - _internal/wasm/lib/string_buffer_create.dart
-      - _internal/wasm/lib/string_patch.dart
-      - _internal/wasm/lib/sync_star_patch.dart
-      - _internal/wasm/lib/weak_patch.dart
+        - _internal/wasm/lib/core_patch.dart
+        - _internal/vm_shared/lib/array_patch.dart
+        - _internal/vm_shared/lib/bigint_patch.dart
+        - _internal/vm_shared/lib/bool_patch.dart
+        - _internal/vm_shared/lib/date_patch.dart
+        - _internal/vm_shared/lib/integers_patch.dart
+        - _internal/vm_shared/lib/map_patch.dart
+        - _internal/vm_shared/lib/null_patch.dart
+        - _internal/vm_shared/lib/string_buffer_patch.dart
+        - _internal/wasm/lib/date_patch_patch.dart
+        - _internal/wasm/lib/string_buffer_create.dart
+        - _internal/wasm/lib/string_patch.dart
+        - _internal/wasm/lib/sync_star_patch.dart
+        - _internal/wasm/lib/weak_patch.dart
+    typed_data:
+      uri: typed_data/typed_data.dart
+      patches:
+        - _internal/wasm_js_compatibility/lib/typed_data_patch.dart
+        - _internal/wasm/lib/simd_patch.dart
 
 wasm_common:
   libraries:
@@ -190,8 +197,6 @@
       uri: _http/http.dart
     _simd:
       uri: _internal/wasm/lib/simd.dart
-    _typed_data:
-      uri: _internal/wasm/lib/typed_data.dart
     _internal:
       uri: internal/internal.dart
       patches:
@@ -260,6 +265,13 @@
     math:
       uri: math/math.dart
       patches: _internal/wasm/lib/math_patch.dart
+
+wasm_base:
+  include:
+    - target: "wasm_common"
+  libraries:
+    _typed_data:
+      uri: _internal/wasm/lib/typed_data.dart
     typed_data:
       uri: typed_data/typed_data.dart
       patches: