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 1783f624f4713..54ea9eebbb1cd 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 @@ class CkBrowserImageDecoder implements ui.Codec { _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(webDecoder.tracks.ready); @@ -217,7 +218,7 @@ class CkBrowserImageDecoder implements ui.Codec { _debugCheckNotDisposed(); final ImageDecoder webDecoder = await _getOrCreateWebDecoder(); final DecodeResult result = await promiseToFuture( - 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 e153286f711f8..71944deff9eee 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 @@ external JsFlutterConfiguration? get _jsConfiguration; 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 0b6e1abfb7475..abd107d3cb81a 100644 --- a/lib/web_ui/lib/src/engine/dom.dart +++ b/lib/web_ui/lib/src/engine/dom.dart @@ -2260,13 +2260,10 @@ extension DomMediaQueryListExtension on DomMediaQueryList { 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 a8c927963ae1b..0fcbea1600890 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 @@ class HighContrastSupport { /// 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 @@ class HighContrastSupport { } } - 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 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher { /// 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 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher { ? 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 8ea415f76788b..da104f9df002b 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 'platform_dispatcher.dart'; 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 c908bf514575b..bceb7c9d5b81d 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 @@ DomCanvasElement? tryCreateCanvasElement(int width, int height) { } @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 @@ class ImageDecoder { 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 @@ extension ImageDecoderExtension on ImageDecoder { @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 @@ class DecodeResult {} 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 @@ extension DecodeResultExtension on DecodeResult { @staticInterop class DecodeOptions { external factory DecodeOptions({ - required double frameIndex, + required JSNumber frameIndex, }); } @@ -332,16 +342,40 @@ class DecodeOptions { 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 @@ extension ImageTrackListExtension on ImageTrackList { 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 8f0ffbc743b90..22b3eca88790c 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 @@ extension SVGAnimatedLengthExtension on SVGAnimatedLength { 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 @@ const int svgLengthTypeNumber = 1; 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 @@ extension SVGFEBlendCompositeExtension on SVGFECompositeElement { 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 @@ extension SVGAnimatedStringExtension on SVGAnimatedString { 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 @@ extension SVGNumberListExtension on SVGNumberList { 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 ba1c914320f04..79a55b140f880 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 @@ import '../dom.dart'; /// to clear. Delay removal of old visible state to make the /// transition appear smooth. @JS('window.__flutterState') -external List? get hotRestartStore; +external JSArray? get _hotRestartStore; +List? get hotRestartStore => + _hotRestartStore?.toObjectShallow as List?; @JS('window.__flutterState') -external set hotRestartStore(List? nodes); +external set _hotRestartStore(JSArray? nodes); +set hotRestartStore(List? 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 b58fe26cc8b30..f7bc814c70e74 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 @@ class TestSkDeletableMock { deleteCount++; } - JsConstructor get constructor => TestJsConstructor(name: 'TestSkDeletable'); + JsConstructor get constructor => TestJsConstructor(name: + 'TestSkDeletable'.toJS); } @JS() @@ -373,14 +376,14 @@ class TestSkDeletable implements SkDeletable { 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 @@ class TestSkDeletable implements SkDeletable { @anonymous @staticInterop class TestJsConstructor implements JsConstructor { - external factory TestJsConstructor({String name}); + external factory TestJsConstructor({JSString name}); } class TestSkiaObject extends ManagedSkiaObject { diff --git a/lib/web_ui/test/embedder_test.dart b/lib/web_ui/test/embedder_test.dart index ebd5e3c656a23..86a8283870934 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 @@ void testMain() { } @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 aceda511064c8..4ca8529cdf069 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 'package:ui/src/engine.dart'; 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 37cada5529bbd..526dbace857f5 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/src/engine.dart' as engine; 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);