Migrate SVG to JS types (#40401)

diff --git a/lib/web_ui/lib/src/engine/canvaskit/image_web_codecs.dart b/lib/web_ui/lib/src/engine/canvaskit/image_web_codecs.dart
index 1783f62..54ea9ee 100644
--- a/lib/web_ui/lib/src/engine/canvaskit/image_web_codecs.dart
+++ b/lib/web_ui/lib/src/engine/canvaskit/image_web_codecs.dart
@@ -10,6 +10,7 @@
 
 import 'dart:async';
 import 'dart:convert' show base64;
+import 'dart:js_interop';
 import 'dart:math' as math;
 import 'dart:typed_data';
 
@@ -147,18 +148,18 @@
     _cacheExpirationClock.callback = null;
     try {
       final ImageDecoder webDecoder = ImageDecoder(ImageDecoderOptions(
-        type: contentType,
-        data: data,
+        type: contentType.toJS,
+        data: data.toJS,
 
         // Flutter always uses premultiplied alpha when decoding.
-        premultiplyAlpha: 'premultiply',
+        premultiplyAlpha: 'premultiply'.toJS,
         // "default" gives the browser the liberty to convert to display-appropriate
         // color space, typically SRGB, which is what we want.
-        colorSpaceConversion: 'default',
+        colorSpaceConversion: 'default'.toJS,
 
         // Flutter doesn't give the developer a way to customize this, so if this
         // is an animated image we should prefer the animated track.
-        preferAnimation: true,
+        preferAnimation: true.toJS,
       ));
 
       await promiseToFuture<void>(webDecoder.tracks.ready);
@@ -217,7 +218,7 @@
     _debugCheckNotDisposed();
     final ImageDecoder webDecoder = await _getOrCreateWebDecoder();
     final DecodeResult result = await promiseToFuture<DecodeResult>(
-      webDecoder.decode(DecodeOptions(frameIndex: _nextFrameIndex.toDouble())),
+      webDecoder.decode(DecodeOptions(frameIndex: _nextFrameIndex.toJS)),
     );
     final VideoFrame frame = result.image;
     _nextFrameIndex = (_nextFrameIndex + 1) % frameCount;
diff --git a/lib/web_ui/lib/src/engine/configuration.dart b/lib/web_ui/lib/src/engine/configuration.dart
index e153286..71944de 100644
--- a/lib/web_ui/lib/src/engine/configuration.dart
+++ b/lib/web_ui/lib/src/engine/configuration.dart
@@ -44,6 +44,7 @@
 @JS()
 library configuration;
 
+import 'dart:js_interop';
 import 'package:js/js.dart';
 import 'package:meta/meta.dart';
 import 'canvaskit/renderer.dart';
@@ -266,16 +267,35 @@
 class JsFlutterConfiguration {}
 
 extension JsFlutterConfigurationExtension on JsFlutterConfiguration {
-  external String? get canvasKitBaseUrl;
-  external String? get canvasKitVariant;
-  external bool? get canvasKitForceCpuOnly;
-  external double? get canvasKitMaximumSurfaces;
-  external bool? get debugShowSemanticsNodes;
+  @JS('canvasKitBaseUrl')
+  external JSString? get _canvasKitBaseUrl;
+  String? get canvasKitBaseUrl => _canvasKitBaseUrl?.toDart;
+
+  @JS('canvasKitVariant')
+  external JSString? get _canvasKitVariant;
+  String? get canvasKitVariant => _canvasKitVariant?.toDart;
+
+  @JS('canvasKitForceCpuOnly')
+  external JSBoolean? get _canvasKitForceCpuOnly;
+  bool? get canvasKitForceCpuOnly => _canvasKitForceCpuOnly?.toDart;
+
+  @JS('canvasKitMaximumSurfaces')
+  external JSNumber? get _canvasKitMaximumSurfaces;
+  double? get canvasKitMaximumSurfaces => _canvasKitMaximumSurfaces?.toDart;
+
+  @JS('debugShowSemanticsNodes')
+  external JSBoolean? get _debugShowSemanticsNodes;
+  bool? get debugShowSemanticsNodes => _debugShowSemanticsNodes?.toDart;
+
   external DomElement? get hostElement;
-  external String? get renderer;
+
+  @JS('renderer')
+  external JSString? get _renderer;
+  String? get renderer => _renderer?.toDart;
 }
 
 /// A JavaScript entrypoint that allows developer to set rendering backend
 /// at runtime before launching the application.
 @JS('window.flutterWebRenderer')
-external String? get _requestedRendererType;
+external JSString? get __requestedRendererType;
+String? get _requestedRendererType => __requestedRendererType?.toDart;
diff --git a/lib/web_ui/lib/src/engine/dom.dart b/lib/web_ui/lib/src/engine/dom.dart
index 0b6e1ab..abd107d 100644
--- a/lib/web_ui/lib/src/engine/dom.dart
+++ b/lib/web_ui/lib/src/engine/dom.dart
@@ -2260,13 +2260,10 @@
   bool get matches => _matches.toDart;
 
   @JS('addListener')
-  external JSVoid _addListener(JSFunction? listener);
-  void addListener(DomEventListener? listener) => _addListener(listener?.toJS);
+  external JSVoid addListener(JSFunction? listener);
 
   @JS('removeListener')
-  external JSVoid _removeListener(JSFunction? listener);
-  void removeListener(DomEventListener? listener) =>
-      _removeListener(listener?.toJS);
+  external JSVoid removeListener(JSFunction? listener);
 }
 
 @JS()
diff --git a/lib/web_ui/lib/src/engine/platform_dispatcher.dart b/lib/web_ui/lib/src/engine/platform_dispatcher.dart
index a8c9279..0fcbea1 100644
--- a/lib/web_ui/lib/src/engine/platform_dispatcher.dart
+++ b/lib/web_ui/lib/src/engine/platform_dispatcher.dart
@@ -43,8 +43,8 @@
 
   /// Reference to css media query that indicates whether high contrast is on.
   final DomMediaQueryList _highContrastMediaQuery = domWindow.matchMedia(_highContrastMediaQueryString);
-  late final DomEventListener _onHighContrastChangeListener =
-      allowInterop(_onHighContrastChange);
+  late final JSFunction _onHighContrastChangeListener =
+      _onHighContrastChange.toJS;
 
   bool get isHighContrastEnabled => _highContrastMediaQuery.matches;
 
@@ -64,7 +64,7 @@
     }
   }
 
-  void _onHighContrastChange(DomEvent event) {
+  JSVoid _onHighContrastChange(DomEvent event) {
     final DomMediaQueryListEvent mqEvent = event as DomMediaQueryListEvent;
     final bool isHighContrastEnabled = mqEvent.matches!;
     for (final HighContrastListener listener in _listeners) {
@@ -1031,7 +1031,7 @@
   /// A callback that is invoked whenever [_brightnessMediaQuery] changes value.
   ///
   /// Updates the [_platformBrightness] with the new user preference.
-  DomEventListener? _brightnessMediaQueryListener;
+  JSFunction? _brightnessMediaQueryListener;
 
   /// Set the callback function for listening changes in [_brightnessMediaQuery] value.
   void _addBrightnessMediaQueryListener() {
@@ -1039,12 +1039,12 @@
         ? ui.Brightness.dark
         : ui.Brightness.light);
 
-    _brightnessMediaQueryListener = allowInterop((DomEvent event) {
+    _brightnessMediaQueryListener = (DomEvent event) {
       final DomMediaQueryListEvent mqEvent =
           event as DomMediaQueryListEvent;
       _updatePlatformBrightness(
           mqEvent.matches! ? ui.Brightness.dark : ui.Brightness.light);
-    });
+    }.toJS;
     _brightnessMediaQuery.addListener(_brightnessMediaQueryListener);
   }
 
diff --git a/lib/web_ui/lib/src/engine/profiler.dart b/lib/web_ui/lib/src/engine/profiler.dart
index 8ea415f..da104f9 100644
--- a/lib/web_ui/lib/src/engine/profiler.dart
+++ b/lib/web_ui/lib/src/engine/profiler.dart
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:js_interop';
 
 import 'package:js/js.dart';
 import 'package:ui/ui.dart' as ui;
@@ -12,7 +13,8 @@
 import 'safe_browser_api.dart';
 
 @JS('window._flutter_internal_on_benchmark')
-external Object? get onBenchmark;
+external JSAny? get _onBenchmark;
+Object? get onBenchmark => _onBenchmark?.toObjectShallow;
 
 /// A function that computes a value of type [R].
 ///
diff --git a/lib/web_ui/lib/src/engine/safe_browser_api.dart b/lib/web_ui/lib/src/engine/safe_browser_api.dart
index c908bf5..bceb7c9 100644
--- a/lib/web_ui/lib/src/engine/safe_browser_api.dart
+++ b/lib/web_ui/lib/src/engine/safe_browser_api.dart
@@ -12,6 +12,7 @@
 library browser_api;
 
 import 'dart:async';
+import 'dart:js_interop';
 import 'dart:js_util' as js_util;
 import 'dart:math' as math;
 import 'dart:typed_data';
@@ -201,7 +202,9 @@
 }
 
 @JS('window.ImageDecoder')
-external Object? get _imageDecoderConstructor;
+external JSAny? get __imageDecoderConstructor;
+Object? get _imageDecoderConstructor =>
+    __imageDecoderConstructor?.toObjectShallow;
 
 /// Environment variable that allows the developer to opt out of using browser's
 /// `ImageDecoder` API, and use the WASM codecs bundled with CanvasKit.
@@ -265,9 +268,13 @@
 
 extension ImageDecoderExtension on ImageDecoder {
   external ImageTrackList get tracks;
-  external bool get complete;
+
+  @JS('complete')
+  external JSBoolean get _complete;
+  bool get complete => _complete.toDart;
+
   external JsPromise decode(DecodeOptions options);
-  external void close();
+  external JSVoid close();
 }
 
 /// Options passed to the `ImageDecoder` constructor.
@@ -280,13 +287,13 @@
 @staticInterop
 class ImageDecoderOptions {
   external factory ImageDecoderOptions({
-    required String type,
-    required Uint8List data,
-    required String premultiplyAlpha,
-    int? desiredWidth,
-    int? desiredHeight,
-    required String colorSpaceConversion,
-    required bool preferAnimation,
+    required JSString type,
+    required JSUint8Array data,
+    required JSString premultiplyAlpha,
+    JSNumber? desiredWidth,
+    JSNumber? desiredHeight,
+    required JSString colorSpaceConversion,
+    required JSBoolean preferAnimation,
   });
 }
 
@@ -302,7 +309,10 @@
 
 extension DecodeResultExtension on DecodeResult {
   external VideoFrame get image;
-  external bool get complete;
+
+  @JS('complete')
+  external JSBoolean get _complete;
+  bool get complete => _complete.toDart;
 }
 
 /// Options passed to [ImageDecoder.decode].
@@ -315,7 +325,7 @@
 @staticInterop
 class DecodeOptions {
   external factory DecodeOptions({
-    required double frameIndex,
+    required JSNumber frameIndex,
   });
 }
 
@@ -332,16 +342,40 @@
 class VideoFrame implements DomCanvasImageSource {}
 
 extension VideoFrameExtension on VideoFrame {
-  external double allocationSize();
-  external JsPromise copyTo(Object destination);
-  external String? get format;
-  external double get codedWidth;
-  external double get codedHeight;
-  external double get displayWidth;
-  external double get displayHeight;
-  external double? get duration;
+  @JS('allocationSize')
+  external JSNumber _allocationSize();
+  double allocationSize() => _allocationSize().toDart;
+
+  @JS('copyTo')
+  external JsPromise _copyTo(JSAny destination);
+  JsPromise copyTo(Object destination) => _copyTo(destination.toJSAnyShallow);
+
+  @JS('format')
+  external JSString? get _format;
+  String? get format => _format?.toDart;
+
+  @JS('codedWidth')
+  external JSNumber get _codedWidth;
+  double get codedWidth => _codedWidth.toDart;
+
+  @JS('codedHeight')
+  external JSNumber get _codedHeight;
+  double get codedHeight => _codedHeight.toDart;
+
+  @JS('displayWidth')
+  external JSNumber get _displayWidth;
+  double get displayWidth => _displayWidth.toDart;
+
+  @JS('displayHeight')
+  external JSNumber get _displayHeight;
+  double get displayHeight => _displayHeight.toDart;
+
+  @JS('duration')
+  external JSNumber? get _duration;
+  double? get duration => _duration?.toDart;
+
   external VideoFrame clone();
-  external void close();
+  external JSVoid close();
 }
 
 /// Corresponds to the browser's `ImageTrackList` type.
@@ -370,8 +404,13 @@
 class ImageTrack {}
 
 extension ImageTrackExtension on ImageTrack {
-  external double get repetitionCount;
-  external double get frameCount;
+  @JS('repetitionCount')
+  external JSNumber get _repetitionCount;
+  double get repetitionCount => _repetitionCount.toDart;
+
+  @JS('frameCount')
+  external JSNumber get _frameCount;
+  double get frameCount => _frameCount.toDart;
 }
 
 void scaleCanvas2D(Object context2d, num x, num y) {
diff --git a/lib/web_ui/lib/src/engine/svg.dart b/lib/web_ui/lib/src/engine/svg.dart
index 8f0ffbc..22b3eca 100644
--- a/lib/web_ui/lib/src/engine/svg.dart
+++ b/lib/web_ui/lib/src/engine/svg.dart
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'dart:js_interop';
 import 'package:js/js.dart';
 
 import 'dom.dart';
@@ -91,8 +92,14 @@
 class SVGLength {}
 
 extension SVGLengthExtension on SVGLength {
-  external set valueAsString(String? value);
-  external void newValueSpecifiedUnits(int unitType, num valueInSpecifiedUnits);
+  @JS('valueAsString')
+  external set _valueAsString(JSString? value);
+  set valueAsString(String? value) => _valueAsString = value?.toJS;
+
+  @JS('newValueSpecifiedUnits')
+  external JSVoid _newValueSpecifiedUnits(JSNumber unitType, JSNumber valueInSpecifiedUnits);
+  void newValueSpecifiedUnits(int unitType, num valueInSpecifiedUnits) =>
+      _newValueSpecifiedUnits(unitType.toJS, valueInSpecifiedUnits.toJS);
 }
 
 const int svgLengthTypeNumber = 1;
@@ -102,7 +109,9 @@
 class SVGAnimatedEnumeration {}
 
 extension SVGAnimatedEnumerationExtenson on SVGAnimatedEnumeration {
-  external set baseVal(int? value);
+  @JS('baseVal')
+  external set _baseVal(JSNumber? value);
+  set baseVal(int? value) => _baseVal = value?.toJS;
 }
 
 @JS()
@@ -186,7 +195,9 @@
 class SVGAnimatedString {}
 
 extension SVGAnimatedStringExtension on SVGAnimatedString {
-  external set baseVal(String? value);
+  @JS('baseVal')
+  external set _baseVal(JSString? value);
+  set baseVal(String? value) => _baseVal = value?.toJS;
 }
 
 @JS()
@@ -194,7 +205,9 @@
 class SVGAnimatedNumber {}
 
 extension SVGAnimatedNumberExtension on SVGAnimatedNumber {
-  external set baseVal(num? value);
+  @JS('baseVal')
+  external set _baseVal(JSNumber? value);
+  set baseVal(num? value) => _baseVal = value?.toJS;
 }
 
 @JS()
@@ -218,5 +231,7 @@
 class SVGNumber {}
 
 extension SVGNumberExtension on SVGNumber {
-  external set value(num? value);
+  @JS('value')
+  external set _value(JSNumber? value);
+  set value(num? v) => _value = v?.toJS;
 }
diff --git a/lib/web_ui/lib/src/engine/view_embedder/hot_restart_cache_handler.dart b/lib/web_ui/lib/src/engine/view_embedder/hot_restart_cache_handler.dart
index ba1c914..79a55b1 100644
--- a/lib/web_ui/lib/src/engine/view_embedder/hot_restart_cache_handler.dart
+++ b/lib/web_ui/lib/src/engine/view_embedder/hot_restart_cache_handler.dart
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'dart:js_interop';
+
 import 'package:js/js.dart';
 import 'package:ui/src/engine.dart';
 
@@ -11,10 +13,14 @@
 /// to clear.  Delay removal of old visible state to make the
 /// transition appear smooth.
 @JS('window.__flutterState')
-external List<Object?>? get hotRestartStore;
+external JSArray? get _hotRestartStore;
+List<Object?>? get hotRestartStore =>
+    _hotRestartStore?.toObjectShallow as List<Object>?;
 
 @JS('window.__flutterState')
-external set hotRestartStore(List<Object?>? nodes);
+external set _hotRestartStore(JSArray? nodes);
+set hotRestartStore(List<Object?>? nodes) =>
+    _hotRestartStore = nodes?.toJSAnyShallow as JSArray?;
 
 /// Handles [DomElement]s that need to be removed after a hot-restart.
 ///
diff --git a/lib/web_ui/test/canvaskit/skia_objects_cache_test.dart b/lib/web_ui/test/canvaskit/skia_objects_cache_test.dart
index b58fe26..f7bc814 100644
--- a/lib/web_ui/test/canvaskit/skia_objects_cache_test.dart
+++ b/lib/web_ui/test/canvaskit/skia_objects_cache_test.dart
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'dart:js_interop';
+
 import 'package:js/js.dart';
 
 import 'package:test/bootstrap/browser.dart';
@@ -363,7 +365,8 @@
     deleteCount++;
   }
 
-  JsConstructor get constructor => TestJsConstructor(name: 'TestSkDeletable');
+  JsConstructor get constructor => TestJsConstructor(name:
+      'TestSkDeletable'.toJS);
 }
 
 @JS()
@@ -373,14 +376,14 @@
   factory TestSkDeletable() {
     final TestSkDeletableMock mock = TestSkDeletableMock();
     return TestSkDeletable._(
-        isDeleted: allowInterop(() => mock.isDeleted()),
-        delete: allowInterop(() => mock.delete()),
+        isDeleted: () { return mock.isDeleted(); }.toJS,
+        delete: () { return mock.delete(); }.toJS,
         constructor: mock.constructor);
   }
 
   external factory TestSkDeletable._({
-    bool Function() isDeleted,
-    void Function() delete,
+    JSFunction isDeleted,
+    JSFunction delete,
     JsConstructor constructor});
 }
 
@@ -388,7 +391,7 @@
 @anonymous
 @staticInterop
 class TestJsConstructor implements JsConstructor {
-  external factory TestJsConstructor({String name});
+  external factory TestJsConstructor({JSString name});
 }
 
 class TestSkiaObject extends ManagedSkiaObject<SkPaint> {
diff --git a/lib/web_ui/test/embedder_test.dart b/lib/web_ui/test/embedder_test.dart
index ebd5e3c..86a8283 100644
--- a/lib/web_ui/test/embedder_test.dart
+++ b/lib/web_ui/test/embedder_test.dart
@@ -4,6 +4,7 @@
 @JS()
 library embedder_test; // We need this to mess with the ShadowDOM.
 
+import 'dart:js_interop';
 import 'package:js/js.dart';
 import 'package:test/bootstrap/browser.dart';
 import 'package:test/test.dart';
@@ -112,7 +113,9 @@
 }
 
 @JS('Element.prototype.attachShadow')
-external dynamic get attachShadow;
+external JSAny? get _attachShadow;
+dynamic get attachShadow => _attachShadow?.toObjectShallow;
 
 @JS('Element.prototype.attachShadow')
-external set attachShadow(dynamic x);
+external set _attachShadow(JSAny? x);
+set attachShadow(Object? x) => _attachShadow = x?.toJSAnyShallow;
diff --git a/lib/web_ui/test/engine/profiler_test.dart b/lib/web_ui/test/engine/profiler_test.dart
index aceda51..4ca8529 100644
--- a/lib/web_ui/test/engine/profiler_test.dart
+++ b/lib/web_ui/test/engine/profiler_test.dart
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'dart:js_interop';
 import 'package:js/js.dart';
 import 'package:test/bootstrap/browser.dart';
 import 'package:test/test.dart';
@@ -10,7 +11,8 @@
 import '../spy.dart';
 
 @JS('window._flutter_internal_on_benchmark')
-external set onBenchmark (Object? object);
+external set _onBenchmark (JSAny? object);
+set onBenchmark (Object? object) => _onBenchmark = object?.toJSAnyShallow;
 
 void main() {
   internalBootstrapBrowserTest(() => testMain);
diff --git a/lib/web_ui/test/initialization_test.dart b/lib/web_ui/test/initialization_test.dart
index 37cada5..526dbac 100644
--- a/lib/web_ui/test/initialization_test.dart
+++ b/lib/web_ui/test/initialization_test.dart
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'dart:js_interop';
 import 'package:js/js.dart';
 import 'package:js/js_util.dart' as js_util;
 import 'package:test/bootstrap/browser.dart';
@@ -10,7 +11,8 @@
 import 'package:ui/ui.dart' as ui;
 
 @JS('_flutter')
-external set loader(Object? loader);
+external set _loader(JSAny? loader);
+set loader(Object? l) => _loader = l?.toJSAnyShallow;
 
 @JS('_flutter.loader.didCreateEngineInitializer')
 external set didCreateEngineInitializer(Object? callback);