From 7cfaf04fa9781d5287af8b348ea1cc1cf5ef701d Mon Sep 17 00:00:00 2001 From: Srujan Gaddam <58529443+srujzs@users.noreply.github.com> Date: Fri, 28 Mar 2025 10:43:50 -0700 Subject: [PATCH] [web] Remove package:js in favor of dart:js_interop (#165324) Removes package:js and uses dart:js_interop instead This is taken directly from https://github.com/flutter/flutter/pull/164254 and will be iterated on. ---- Initial commit is the original PR % rebasing. Follow-up commits address test/analysis failures and commits after those clean up JS interop code: - Remove remaining uses of `@staticInterop`. - Code that uses JSBoolean, JSString, or JSNumber are mostly historical relics due to not supporting primitives in externals. Remove the redirecting functions and let the compiler handles the conversions. - Replace domInstanceOfString calls with isA and add @JS annotations to all extension types where needed. - Remove unnecessary @JS annotations. - Remove unneeded implements JSObject clauses. - Standardize naming of extension types in some cases. - Remove JSVoid in favor of void. - Enabled invalid_runtime_checks_with_js_interop_types lint. - Removed unnecessary JSUint8Array constructors. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [ ] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [ ] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. --------- Co-authored-by: Kevin Moore --- .../flutter/lib/web_ui/analysis_options.yaml | 1 - .../lib/src/engine/browser_detection.dart | 2 +- .../src/engine/canvaskit/canvaskit_api.dart | 2015 +++---------- .../lib/src/engine/canvaskit/image.dart | 18 +- .../engine/canvaskit/image_web_codecs.dart | 6 +- .../src/engine/canvaskit/native_memory.dart | 8 +- .../src/engine/canvaskit/render_canvas.dart | 9 +- .../lib/src/engine/canvaskit/surface.dart | 38 +- .../web_ui/lib/src/engine/configuration.dart | 72 +- .../lib/web_ui/lib/src/engine/dom.dart | 2666 +++++------------ .../web_ui/lib/src/engine/high_contrast.dart | 6 +- .../web_ui/lib/src/engine/image_decoder.dart | 18 +- .../lib/src/engine/js_interop/js_app.dart | 42 +- .../lib/src/engine/js_interop/js_loader.dart | 34 +- .../src/engine/js_interop/js_typed_data.dart | 24 +- .../lib/src/engine/keyboard_binding.dart | 8 +- .../lib/src/engine/platform_dispatcher.dart | 23 +- .../view_focus_binding.dart | 4 +- .../lib/src/engine/pointer_binding.dart | 14 +- .../web_ui/lib/src/engine/raw_keyboard.dart | 3 +- .../lib/src/engine/safe_browser_api.dart | 137 +- .../lib/web_ui/lib/src/engine/scene_view.dart | 6 +- .../lib/src/engine/semantics/focusable.dart | 8 +- .../src/engine/semantics/incrementable.dart | 2 +- .../lib/src/engine/semantics/route.dart | 1 - .../lib/src/engine/semantics/scrollable.dart | 2 +- .../lib/src/engine/semantics/semantics.dart | 19 +- .../engine/semantics/semantics_helper.dart | 5 +- .../lib/src/engine/semantics/text_field.dart | 12 +- .../src/engine/skwasm/skwasm_impl/codecs.dart | 6 +- .../engine/skwasm/skwasm_impl/filters.dart | 4 +- .../skwasm/skwasm_impl/font_collection.dart | 18 +- .../src/engine/skwasm/skwasm_impl/image.dart | 10 +- .../engine/skwasm/skwasm_impl/paragraph.dart | 28 +- .../src/engine/skwasm/skwasm_impl/path.dart | 2 +- .../skwasm/skwasm_impl/path_metrics.dart | 8 +- .../engine/skwasm/skwasm_impl/picture.dart | 6 +- .../skwasm/skwasm_impl/raw/skwasm_module.dart | 12 +- .../engine/skwasm/skwasm_impl/renderer.dart | 8 +- .../engine/skwasm/skwasm_impl/shaders.dart | 8 +- .../engine/skwasm/skwasm_impl/surface.dart | 15 +- .../engine/skwasm/skwasm_impl/vertices.dart | 2 +- .../lib/web_ui/lib/src/engine/svg.dart | 154 +- .../text_editing/composition_aware_mixin.dart | 8 +- .../text_editing/text_capitalization.dart | 6 +- .../src/engine/text_editing/text_editing.dart | 209 +- .../full_page_dimensions_provider.dart | 6 +- .../view_embedder/display_dpr_stream.dart | 7 +- .../hot_restart_cache_handler.dart | 2 +- .../ui_web/src/ui_web/browser_detection.dart | 2 +- .../web_ui/lib/ui_web/src/ui_web/images.dart | 2 +- .../ui_web/navigation/platform_location.dart | 7 +- engine/src/flutter/lib/web_ui/pubspec.yaml | 1 - .../test/canvaskit/canvas_golden_test.dart | 2 +- .../test/canvaskit/canvaskit_api_test.dart | 6 +- .../test/canvaskit/image_golden_test.dart | 5 +- .../does_not_mock_module_exports_test.dart | 13 +- .../initialization/stores_config_test.dart | 4 +- .../test/canvaskit/native_memory_test.dart | 14 +- .../web_ui/test/canvaskit/surface_test.dart | 20 +- .../lib/web_ui/test/common/matchers.dart | 10 +- .../test/engine/configuration_test.dart | 30 +- .../test/engine/dom_http_fetch_test.dart | 8 +- .../engine/image_format_detector_test.dart | 4 +- .../test/engine/pointer_binding_test.dart | 7 +- .../lib/web_ui/test/engine/routing_test.dart | 3 +- .../web_ui/test/engine/scene_view_test.dart | 5 +- .../test/engine/semantics/semantics_test.dart | 2 +- .../web_ui/test/engine/text_editing_test.dart | 9 +- .../view_embedder/dom_manager_test.dart | 2 +- .../flutter_views_proxy_test.dart | 7 +- .../web_ui/test/fallbacks/fallbacks_test.dart | 4 +- .../image/html_image_element_codec_test.dart | 1 - .../lib/web_ui/test/ui/image_golden_test.dart | 11 +- engine/src/flutter/web_sdk/sdk_rewriter.dart | 3 +- .../flutter/web_sdk/test/js_access_test.dart | 2 +- .../web_sdk/test/sdk_rewriter_test.dart | 6 +- .../web_engine_tester/lib/static/host.dart | 124 +- 78 files changed, 1771 insertions(+), 4265 deletions(-) diff --git a/engine/src/flutter/lib/web_ui/analysis_options.yaml b/engine/src/flutter/lib/web_ui/analysis_options.yaml index 3a172dcb3c0..0938119b506 100644 --- a/engine/src/flutter/lib/web_ui/analysis_options.yaml +++ b/engine/src/flutter/lib/web_ui/analysis_options.yaml @@ -10,7 +10,6 @@ linter: rules: avoid_print: false avoid_setters_without_getters: false - invalid_runtime_check_with_js_interop_types: false library_private_types_in_public_api: false no_default_cases: false prefer_relative_imports: false diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/browser_detection.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/browser_detection.dart index bb76f73916f..1d3c6862404 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/browser_detection.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/browser_detection.dart @@ -116,7 +116,7 @@ int? _cachedWebGLVersion; /// /// Our CanvasKit backend is affected due to: https://github.com/emscripten-core/emscripten/issues/11819 int _detectWebGLVersion() { - final DomCanvasElement canvas = createDomCanvasElement(width: 1, height: 1); + final DomHTMLCanvasElement canvas = createDomCanvasElement(width: 1, height: 1); if (canvas.getContext('webgl2') != null) { if (_workAroundBug91333) { return WebGLVersion.webgl1; diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart index c994d295c37..1ea1ee37e08 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart @@ -46,12 +46,7 @@ external CanvasKit? get windowFlutterCanvasKit; @JS('window.flutterCanvasKitLoaded') external JSPromise? get windowFlutterCanvasKitLoaded; -@JS() -@anonymous -@staticInterop -class CanvasKit {} - -extension CanvasKitExtension on CanvasKit { +extension type CanvasKit(JSObject _) implements JSObject { external SkBlendModeEnum get BlendMode; external SkPaintStyleEnum get PaintStyle; external SkStrokeCapEnum get StrokeCap; @@ -107,32 +102,18 @@ extension CanvasKitExtension on CanvasKit { external SkParagraphBuilderNamespace get ParagraphBuilder; external SkParagraphStyle ParagraphStyle(SkParagraphStyleProperties properties); external SkTextStyle TextStyle(SkTextStyleProperties properties); - external SkSurface MakeWebGLCanvasSurface(DomCanvasElement canvas); - - @JS('MakeSurface') - external SkSurface _MakeSurface(JSNumber width, JSNumber height); - SkSurface MakeSurface(double width, double height) => _MakeSurface(width.toJS, height.toJS); + external SkSurface MakeWebGLCanvasSurface(DomHTMLCanvasElement canvas); + external SkSurface MakeSurface(double width, double height); @JS('getDataBytes') external JSUint8Array _getDataBytes(SkData skData); Uint8List getDataBytes(SkData skData) => _getDataBytes(skData).toDart; // Text decoration enum is embedded in the CanvasKit object itself. - @JS('NoDecoration') - external JSNumber get _NoDecoration; - double get NoDecoration => _NoDecoration.toDartDouble; - - @JS('UnderlineDecoration') - external JSNumber get _UnderlineDecoration; - double get UnderlineDecoration => _UnderlineDecoration.toDartDouble; - - @JS('OverlineDecoration') - external JSNumber get _OverlineDecoration; - double get OverlineDecoration => _OverlineDecoration.toDartDouble; - - @JS('LineThroughDecoration') - external JSNumber get _LineThroughDecoration; - double get LineThroughDecoration => _LineThroughDecoration.toDartDouble; + external double get NoDecoration; + external double get UnderlineDecoration; + external double get OverlineDecoration; + external double get LineThroughDecoration; // End of text decoration enum. external SkTextDecorationStyleEnum get DecorationStyle; @@ -144,54 +125,25 @@ extension CanvasKitExtension on CanvasKit { external FontCollectionNamespace get FontCollection; external SkTypefaceFactory get Typeface; + external double GetWebGLContext(DomHTMLCanvasElement canvas, SkWebGLContextOptions options); @JS('GetWebGLContext') - external JSNumber _GetWebGLContext(DomCanvasElement canvas, SkWebGLContextOptions options); - double GetWebGLContext(DomCanvasElement canvas, SkWebGLContextOptions options) => - _GetWebGLContext(canvas, options).toDartDouble; - - @JS('GetWebGLContext') - external JSNumber _GetOffscreenWebGLContext( + external double GetOffscreenWebGLContext( DomOffscreenCanvas canvas, SkWebGLContextOptions options, ); - double GetOffscreenWebGLContext(DomOffscreenCanvas canvas, SkWebGLContextOptions options) => - _GetOffscreenWebGLContext(canvas, options).toDartDouble; - - @JS('MakeGrContext') - external SkGrContext? _MakeGrContext(JSNumber glContext); - SkGrContext? MakeGrContext(double glContext) => _MakeGrContext(glContext.toJS); - - @JS('MakeOnScreenGLSurface') - external SkSurface? _MakeOnScreenGLSurface( - SkGrContext grContext, - JSNumber width, - JSNumber height, - ColorSpace colorSpace, - JSNumber sampleCount, - JSNumber stencil, - ); - SkSurface? MakeOnScreenGLSurface( + external SkGrContext? MakeGrContext(double glContext); + external SkSurface? MakeOnScreenGLSurface( SkGrContext grContext, double width, double height, ColorSpace colorSpace, int sampleCount, int stencil, - ) => _MakeOnScreenGLSurface( - grContext, - width.toJS, - height.toJS, - colorSpace, - sampleCount.toJS, - stencil.toJS, ); - @JS('MakeRenderTarget') - external SkSurface? _MakeRenderTarget(SkGrContext grContext, JSNumber width, JSNumber height); - SkSurface? MakeRenderTarget(SkGrContext grContext, int width, int height) => - _MakeRenderTarget(grContext, width.toJS, height.toJS); + external SkSurface? MakeRenderTarget(SkGrContext grContext, int width, int height); - external SkSurface MakeSWCanvasSurface(DomCanvasElement canvas); + external SkSurface MakeSWCanvasSurface(DomHTMLCanvasElement canvas); @JS('MakeSWCanvasSurface') external SkSurface MakeOffscreenSWCanvasSurface(DomOffscreenCanvas canvas); @@ -204,9 +156,9 @@ extension CanvasKitExtension on CanvasKit { /// parameters specified in [SkImageInfo] passed [SkImage.readPixels] must /// match [info]. @JS('MakeImage') - external SkImage? _MakeImage(SkImageInfo info, JSUint8Array pixels, JSNumber bytesPerRow); + external SkImage? _MakeImage(SkImageInfo info, JSUint8Array pixels, double bytesPerRow); SkImage? MakeImage(SkImageInfo info, Uint8List pixels, double bytesPerRow) => - _MakeImage(info, pixels.toJS, bytesPerRow.toJS); + _MakeImage(info, pixels.toJS, bytesPerRow); @JS('MakeLazyImageFromTextureSource') external SkImage? _MakeLazyImageFromTextureSource2(JSAny src, SkPartialImageInfo info); @@ -214,22 +166,18 @@ extension CanvasKitExtension on CanvasKit { @JS('MakeLazyImageFromTextureSource') external SkImage? _MakeLazyImageFromTextureSource3( JSAny src, - JSNumber zeroSecondArgument, - JSBoolean srcIsPremultiplied, + int zeroSecondArgument, + bool srcIsPremultiplied, ); SkImage? MakeLazyImageFromTextureSourceWithInfo(Object src, SkPartialImageInfo info) => _MakeLazyImageFromTextureSource2(src.toJSAnyShallow, info); SkImage? MakeLazyImageFromImageBitmap(DomImageBitmap imageBitmap, bool hasPremultipliedAlpha) => - _MakeLazyImageFromTextureSource3(imageBitmap as JSObject, 0.toJS, hasPremultipliedAlpha.toJS); + _MakeLazyImageFromTextureSource3(imageBitmap, 0, hasPremultipliedAlpha); } -@JS() -@staticInterop -class CanvasKitModule {} - -extension CanvasKitModuleExtension on CanvasKitModule { +extension type CanvasKitModule(JSObject _) implements JSObject { @JS('default') external JSPromise defaultExport(CanvasKitInitOptions options); } @@ -238,87 +186,47 @@ typedef LocateFileCallback = String Function(String file, String unusedBase); JSFunction createLocateFileCallback(LocateFileCallback callback) => callback.toJS; -@JS() -@anonymous -@staticInterop -class CanvasKitInitOptions { - external factory CanvasKitInitOptions({required JSFunction locateFile}); +extension type CanvasKitInitOptions._(JSObject _) implements JSObject { + external CanvasKitInitOptions({required JSFunction locateFile}); } @JS('window.flutterCanvasKit.ColorSpace.SRGB') external ColorSpace get SkColorSpaceSRGB; -@JS() -@staticInterop -class ColorSpace {} +extension type ColorSpace(JSObject _) implements JSObject {} -@JS() -@anonymous -@staticInterop -class SkWebGLContextOptions { - factory SkWebGLContextOptions({ +extension type SkWebGLContextOptions._(JSObject _) implements JSObject { + external factory SkWebGLContextOptions({ required double antialias, // WebGL version: 1 or 2. required double majorVersion, - }) => SkWebGLContextOptions._(antialias: antialias.toJS, majorVersion: majorVersion.toJS); - external factory SkWebGLContextOptions._({ - required JSNumber antialias, - // WebGL version: 1 or 2. - required JSNumber majorVersion, }); } @JS('window.flutterCanvasKit.Surface') -@staticInterop -class SkSurface {} - -extension SkSurfaceExtension on SkSurface { +extension type SkSurface(JSObject _) implements JSObject { external SkCanvas getCanvas(); - external JSVoid flush(); - - @JS('width') - external JSNumber _width(); - double width() => _width().toDartDouble; - - @JS('height') - external JSNumber _height(); - double height() => _height().toDartDouble; - - external JSVoid dispose(); + external void flush(); + external double width(); + external double height(); + external void dispose(); external SkImage makeImageSnapshot(); } -@JS() -@staticInterop -class SkGrContext {} - -extension SkGrContextExtension on SkGrContext { - @JS('setResourceCacheLimitBytes') - external JSVoid _setResourceCacheLimitBytes(JSNumber limit); - void setResourceCacheLimitBytes(double limit) => _setResourceCacheLimitBytes(limit.toJS); - - external JSVoid releaseResourcesAndAbandonContext(); - external JSVoid delete(); +extension type SkGrContext(JSObject _) implements JSObject { + external void setResourceCacheLimitBytes(double limit); + external void releaseResourcesAndAbandonContext(); + external void delete(); } -@JS() -@anonymous -@staticInterop -class SkFontSlantEnum {} - -extension SkFontSlantEnumExtension on SkFontSlantEnum { +extension type SkFontSlantEnum(JSObject _) implements JSObject { external SkFontSlant get Upright; external SkFontSlant get Italic; } @JS('window.flutterCanvasKit.FontSlant') -@staticInterop -class SkFontSlant {} - -extension SkFontSlantExtension on SkFontSlant { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkFontSlant(JSObject _) implements JSObject { + external double get value; } final List _skFontSlants = [ @@ -330,12 +238,7 @@ SkFontSlant toSkFontSlant(ui.FontStyle style) { return _skFontSlants[style.index]; } -@JS() -@anonymous -@staticInterop -class SkFontWeightEnum {} - -extension SkFontWeightEnumExtension on SkFontWeightEnum { +extension type SkFontWeightEnum(JSObject _) implements JSObject { external SkFontWeight get Thin; external SkFontWeight get ExtraLight; external SkFontWeight get Light; @@ -347,14 +250,8 @@ extension SkFontWeightEnumExtension on SkFontWeightEnum { external SkFontWeight get ExtraBlack; } -@JS() -@staticInterop -class SkFontWeight {} - -extension SkFontWeightExtension on SkFontWeight { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkFontWeight(JSObject _) implements JSObject { + external double get value; } final List _skFontWeights = [ @@ -373,23 +270,13 @@ SkFontWeight toSkFontWeight(ui.FontWeight weight) { return _skFontWeights[weight.index]; } -@JS() -@staticInterop -class SkAffinityEnum {} - -extension SkAffinityEnumExtension on SkAffinityEnum { +extension type SkAffinityEnum(JSObject _) implements JSObject { external SkAffinity get Upstream; external SkAffinity get Downstream; } -@JS() -@staticInterop -class SkAffinity {} - -extension SkAffinityExtension on SkAffinity { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkAffinity(JSObject _) implements JSObject { + external double get value; } final List _skAffinitys = [ @@ -401,23 +288,13 @@ SkAffinity toSkAffinity(ui.TextAffinity affinity) { return _skAffinitys[affinity.index]; } -@JS() -@staticInterop -class SkTextDirectionEnum {} - -extension SkTextDirectionEnumExtension on SkTextDirectionEnum { +extension type SkTextDirectionEnum(JSObject _) implements JSObject { external SkTextDirection get RTL; external SkTextDirection get LTR; } -@JS() -@staticInterop -class SkTextDirection {} - -extension SkTextDirectionExtension on SkTextDirection { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkTextDirection(JSObject _) implements JSObject { + external double get value; } // Flutter enumerates text directions as RTL, LTR, while CanvasKit @@ -431,11 +308,7 @@ SkTextDirection toSkTextDirection(ui.TextDirection direction) { return _skTextDirections[direction.index]; } -@JS() -@staticInterop -class SkTextAlignEnum {} - -extension SkTextAlignEnumExtension on SkTextAlignEnum { +extension type SkTextAlignEnum(JSObject _) implements JSObject { external SkTextAlign get Left; external SkTextAlign get Right; external SkTextAlign get Center; @@ -444,14 +317,8 @@ extension SkTextAlignEnumExtension on SkTextAlignEnum { external SkTextAlign get End; } -@JS() -@staticInterop -class SkTextAlign {} - -extension SkTextAlignExtension on SkTextAlign { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkTextAlign(JSObject _) implements JSObject { + external double get value; } final List _skTextAligns = [ @@ -467,25 +334,15 @@ SkTextAlign toSkTextAlign(ui.TextAlign align) { return _skTextAligns[align.index]; } -@JS() -@staticInterop -class SkTextHeightBehaviorEnum {} - -extension SkTextHeightBehaviorEnumExtension on SkTextHeightBehaviorEnum { +extension type SkTextHeightBehaviorEnum(JSObject _) implements JSObject { external SkTextHeightBehavior get All; external SkTextHeightBehavior get DisableFirstAscent; external SkTextHeightBehavior get DisableLastDescent; external SkTextHeightBehavior get DisableAll; } -@JS() -@staticInterop -class SkTextHeightBehavior {} - -extension SkTextHeightBehaviorExtension on SkTextHeightBehavior { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkTextHeightBehavior(JSObject _) implements JSObject { + external double get value; } final List _skTextHeightBehaviors = [ @@ -502,11 +359,7 @@ SkTextHeightBehavior toSkTextHeightBehavior(ui.TextHeightBehavior behavior) { return _skTextHeightBehaviors[index]; } -@JS() -@staticInterop -class SkRectHeightStyleEnum {} - -extension SkRectHeightStyleEnumExtension on SkRectHeightStyleEnum { +extension type SkRectHeightStyleEnum(JSObject _) implements JSObject { external SkRectHeightStyle get Tight; external SkRectHeightStyle get Max; external SkRectHeightStyle get IncludeLineSpacingMiddle; @@ -515,14 +368,8 @@ extension SkRectHeightStyleEnumExtension on SkRectHeightStyleEnum { external SkRectHeightStyle get Strut; } -@JS() -@staticInterop -class SkRectHeightStyle {} - -extension SkRectHeightStyleExtension on SkRectHeightStyle { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkRectHeightStyle(JSObject _) implements JSObject { + external double get value; } final List _skRectHeightStyles = [ @@ -538,23 +385,13 @@ SkRectHeightStyle toSkRectHeightStyle(ui.BoxHeightStyle style) { return _skRectHeightStyles[style.index]; } -@JS() -@staticInterop -class SkRectWidthStyleEnum {} - -extension SkRectWidthStyleEnumExtension on SkRectWidthStyleEnum { +extension type SkRectWidthStyleEnum(JSObject _) implements JSObject { external SkRectWidthStyle get Tight; external SkRectWidthStyle get Max; } -@JS() -@staticInterop -class SkRectWidthStyle {} - -extension SkRectWidthStyleExtension on SkRectWidthStyle { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkRectWidthStyle(JSObject _) implements JSObject { + external double get value; } final List _skRectWidthStyles = [ @@ -567,24 +404,14 @@ SkRectWidthStyle toSkRectWidthStyle(ui.BoxWidthStyle style) { return _skRectWidthStyles[index < 2 ? index : 0]; } -@JS() -@staticInterop -class SkVertexModeEnum {} - -extension SkVertexModeEnumExtension on SkVertexModeEnum { +extension type SkVertexModeEnum(JSObject _) implements JSObject { external SkVertexMode get Triangles; external SkVertexMode get TrianglesStrip; external SkVertexMode get TriangleFan; } -@JS() -@staticInterop -class SkVertexMode {} - -extension SkVertexModeExtension on SkVertexMode { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkVertexMode(JSObject _) implements JSObject { + external double get value; } final List _skVertexModes = [ @@ -597,24 +424,14 @@ SkVertexMode toSkVertexMode(ui.VertexMode mode) { return _skVertexModes[mode.index]; } -@JS() -@staticInterop -class SkPointModeEnum {} - -extension SkPointModeEnumExtension on SkPointModeEnum { +extension type SkPointModeEnum(JSObject _) implements JSObject { external SkPointMode get Points; external SkPointMode get Lines; external SkPointMode get Polygon; } -@JS() -@staticInterop -class SkPointMode {} - -extension SkPointModeExtension on SkPointMode { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkPointMode(JSObject _) implements JSObject { + external double get value; } final List _skPointModes = [ @@ -627,23 +444,13 @@ SkPointMode toSkPointMode(ui.PointMode mode) { return _skPointModes[mode.index]; } -@JS() -@staticInterop -class SkClipOpEnum {} - -extension SkClipOpEnumExtension on SkClipOpEnum { +extension type SkClipOpEnum(JSObject _) implements JSObject { external SkClipOp get Difference; external SkClipOp get Intersect; } -@JS() -@staticInterop -class SkClipOp {} - -extension SkClipOpExtension on SkClipOp { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkClipOp(JSObject _) implements JSObject { + external double get value; } final List _skClipOps = [ @@ -655,23 +462,13 @@ SkClipOp toSkClipOp(ui.ClipOp clipOp) { return _skClipOps[clipOp.index]; } -@JS() -@staticInterop -class SkFillTypeEnum {} - -extension SkFillTypeEnumExtension on SkFillTypeEnum { +extension type SkFillTypeEnum(JSObject _) implements JSObject { external SkFillType get Winding; external SkFillType get EvenOdd; } -@JS() -@staticInterop -class SkFillType {} - -extension SkFillTypeExtension on SkFillType { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkFillType(JSObject _) implements JSObject { + external double get value; } final List _skFillTypes = [ @@ -683,11 +480,7 @@ SkFillType toSkFillType(ui.PathFillType fillType) { return _skFillTypes[fillType.index]; } -@JS() -@staticInterop -class SkPathOpEnum {} - -extension SkPathOpEnumExtension on SkPathOpEnum { +extension type SkPathOpEnum(JSObject _) implements JSObject { external SkPathOp get Difference; external SkPathOp get Intersect; external SkPathOp get Union; @@ -695,14 +488,8 @@ extension SkPathOpEnumExtension on SkPathOpEnum { external SkPathOp get ReverseDifference; } -@JS() -@staticInterop -class SkPathOp {} - -extension SkPathOpExtension on SkPathOp { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkPathOp(JSObject _) implements JSObject { + external double get value; } final List _skPathOps = [ @@ -717,25 +504,15 @@ SkPathOp toSkPathOp(ui.PathOperation pathOp) { return _skPathOps[pathOp.index]; } -@JS() -@staticInterop -class SkBlurStyleEnum {} - -extension SkBlurStyleEnumExtension on SkBlurStyleEnum { +extension type SkBlurStyleEnum(JSObject _) implements JSObject { external SkBlurStyle get Normal; external SkBlurStyle get Solid; external SkBlurStyle get Outer; external SkBlurStyle get Inner; } -@JS() -@staticInterop -class SkBlurStyle {} - -extension SkBlurStyleExtension on SkBlurStyle { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkBlurStyle(JSObject _) implements JSObject { + external double get value; } final List _skBlurStyles = [ @@ -749,24 +526,14 @@ SkBlurStyle toSkBlurStyle(ui.BlurStyle style) { return _skBlurStyles[style.index]; } -@JS() -@staticInterop -class SkStrokeCapEnum {} - -extension SkStrokeCapEnumExtension on SkStrokeCapEnum { +extension type SkStrokeCapEnum(JSObject _) implements JSObject { external SkStrokeCap get Butt; external SkStrokeCap get Round; external SkStrokeCap get Square; } -@JS() -@staticInterop -class SkStrokeCap {} - -extension SkStrokeCapExtension on SkStrokeCap { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkStrokeCap(JSObject _) implements JSObject { + external double get value; } final List _skStrokeCaps = [ @@ -779,23 +546,13 @@ SkStrokeCap toSkStrokeCap(ui.StrokeCap strokeCap) { return _skStrokeCaps[strokeCap.index]; } -@JS() -@staticInterop -class SkPaintStyleEnum {} - -extension SkPaintStyleEnumExtension on SkPaintStyleEnum { +extension type SkPaintStyleEnum(JSObject _) implements JSObject { external SkPaintStyle get Stroke; external SkPaintStyle get Fill; } -@JS() -@staticInterop -class SkPaintStyle {} - -extension SkPaintStyleExtension on SkPaintStyle { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkPaintStyle(JSObject _) implements JSObject { + external double get value; } final List _skPaintStyles = [ @@ -807,11 +564,7 @@ SkPaintStyle toSkPaintStyle(ui.PaintingStyle paintStyle) { return _skPaintStyles[paintStyle.index]; } -@JS() -@staticInterop -class SkBlendModeEnum {} - -extension SkBlendModeEnumExtension on SkBlendModeEnum { +extension type SkBlendModeEnum(JSObject _) implements JSObject { external SkBlendMode get Clear; external SkBlendMode get Src; external SkBlendMode get Dst; @@ -843,14 +596,8 @@ extension SkBlendModeEnumExtension on SkBlendModeEnum { external SkBlendMode get Luminosity; } -@JS() -@staticInterop -class SkBlendMode {} - -extension SkBlendModeExtension on SkBlendMode { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkBlendMode(JSObject _) implements JSObject { + external double get value; } final List _skBlendModes = [ @@ -889,24 +636,14 @@ SkBlendMode toSkBlendMode(ui.BlendMode blendMode) { return _skBlendModes[blendMode.index]; } -@JS() -@staticInterop -class SkStrokeJoinEnum {} - -extension SkStrokeJoinEnumExtension on SkStrokeJoinEnum { +extension type SkStrokeJoinEnum(JSObject _) implements JSObject { external SkStrokeJoin get Miter; external SkStrokeJoin get Round; external SkStrokeJoin get Bevel; } -@JS() -@staticInterop -class SkStrokeJoin {} - -extension SkStrokeJoinExtension on SkStrokeJoin { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkStrokeJoin(JSObject _) implements JSObject { + external double get value; } final List _skStrokeJoins = [ @@ -919,25 +656,15 @@ SkStrokeJoin toSkStrokeJoin(ui.StrokeJoin strokeJoin) { return _skStrokeJoins[strokeJoin.index]; } -@JS() -@staticInterop -class SkTileModeEnum {} - -extension SkTileModeEnumExtension on SkTileModeEnum { +extension type SkTileModeEnum(JSObject _) implements JSObject { external SkTileMode get Clamp; external SkTileMode get Repeat; external SkTileMode get Mirror; external SkTileMode get Decal; } -@JS() -@staticInterop -class SkTileMode {} - -extension SkTileModeExtension on SkTileMode { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkTileMode(JSObject _) implements JSObject { + external double get value; } final List _skTileModes = [ @@ -951,23 +678,13 @@ SkTileMode toSkTileMode(ui.TileMode? mode) { return mode == null ? canvasKit.TileMode.Clamp : _skTileModes[mode.index]; } -@JS() -@staticInterop -class SkFilterModeEnum {} - -extension SkFilterModeEnumExtension on SkFilterModeEnum { +extension type SkFilterModeEnum(JSObject _) implements JSObject { external SkFilterMode get Nearest; external SkFilterMode get Linear; } -@JS() -@staticInterop -class SkFilterMode {} - -extension SkFilterModeExtension on SkFilterMode { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkFilterMode(JSObject _) implements JSObject { + external double get value; } SkFilterMode toSkFilterMode(ui.FilterQuality filterQuality) { @@ -976,24 +693,14 @@ SkFilterMode toSkFilterMode(ui.FilterQuality filterQuality) { : canvasKit.FilterMode.Linear; } -@JS() -@staticInterop -class SkMipmapModeEnum {} - -extension SkMipmapModeEnumExtension on SkMipmapModeEnum { +extension type SkMipmapModeEnum(JSObject _) implements JSObject { external SkMipmapMode get None; external SkMipmapMode get Nearest; external SkMipmapMode get Linear; } -@JS() -@staticInterop -class SkMipmapMode {} - -extension SkMipmapModeExtension on SkMipmapMode { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkMipmapMode(JSObject _) implements JSObject { + external double get value; } SkMipmapMode toSkMipmapMode(ui.FilterQuality filterQuality) { @@ -1002,31 +709,17 @@ SkMipmapMode toSkMipmapMode(ui.FilterQuality filterQuality) { : canvasKit.MipmapMode.None; } -@JS() -@staticInterop -class SkAlphaTypeEnum {} - -extension SkAlphaTypeEnumExtension on SkAlphaTypeEnum { +extension type SkAlphaTypeEnum(JSObject _) implements JSObject { external SkAlphaType get Opaque; external SkAlphaType get Premul; external SkAlphaType get Unpremul; } -@JS() -@staticInterop -class SkAlphaType {} - -extension SkAlphaTypeExtension on SkAlphaType { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkAlphaType(JSObject _) implements JSObject { + external double get value; } -@JS() -@staticInterop -class SkColorTypeEnum {} - -extension SkColorTypeEnumExtension on SkColorTypeEnum { +extension type SkColorTypeEnum(JSObject _) implements JSObject { external SkColorType get Alpha_8; external SkColorType get RGB_565; external SkColorType get ARGB_4444; @@ -1040,82 +733,48 @@ extension SkColorTypeEnumExtension on SkColorTypeEnum { external SkColorType get RGBA_F32; } -@JS() -@staticInterop -class SkColorType {} - -extension SkColorTypeExtension on SkColorType { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkColorType(JSObject _) implements JSObject { + external double get value; } -@JS() -@anonymous -@staticInterop -class SkAnimatedImage {} +extension type SkAnimatedImage(JSObject _) implements JSObject { + external double getFrameCount(); -extension SkAnimatedImageExtension on SkAnimatedImage { - @JS('getFrameCount') - external JSNumber _getFrameCount(); - double getFrameCount() => _getFrameCount().toDartDouble; - - @JS('getRepetitionCount') - external JSNumber _getRepetitionCount(); - double getRepetitionCount() => _getRepetitionCount().toDartDouble; + external double getRepetitionCount(); /// Returns duration in milliseconds. - @JS('currentFrameDuration') - external JSNumber _currentFrameDuration(); - double currentFrameDuration() => _currentFrameDuration().toDartDouble; + external double currentFrameDuration(); /// Advances to the next frame and returns its duration in milliseconds. - @JS('decodeNextFrame') - external JSNumber _decodeNextFrame(); - double decodeNextFrame() => _decodeNextFrame().toDartDouble; + external double decodeNextFrame(); external SkImage makeImageAtCurrentFrame(); - @JS('width') - external JSNumber _width(); - double width() => _width().toDartDouble; + external double width(); - @JS('height') - external JSNumber _height(); - double height() => _height().toDartDouble; + external double height(); /// Deletes the C++ object. /// /// This object is no longer usable after calling this method. - external JSVoid delete(); + external void delete(); - @JS('isDeleted') - external JSBoolean _isDeleted(); - bool isDeleted() => _isDeleted().toDart; + external bool isDeleted(); } -@JS() -@anonymous -@staticInterop -class SkImage {} +extension type SkImage(JSObject _) implements JSObject { + external void delete(); -extension SkImageExtension on SkImage { - external JSVoid delete(); + external double width(); - @JS('width') - external JSNumber _width(); - double width() => _width().toDartDouble; - - @JS('height') - external JSNumber _height(); - double height() => _height().toDartDouble; + external double height(); @JS('makeShaderCubic') external SkShader _makeShaderCubic( SkTileMode tileModeX, SkTileMode tileModeY, - JSNumber B, - JSNumber C, + double B, + double C, JSFloat32Array? matrix, // 3x3 matrix ); SkShader makeShaderCubic( @@ -1124,7 +783,7 @@ extension SkImageExtension on SkImage { double B, double C, Float32List? matrix, // 3x3 matrix - ) => _makeShaderCubic(tileModeX, tileModeY, B.toJS, C.toJS, matrix?.toJS); + ) => _makeShaderCubic(tileModeX, tileModeY, B, C, matrix?.toJS); @JS('makeShaderOptions') external SkShader _makeShaderOptions( @@ -1143,28 +802,20 @@ extension SkImageExtension on SkImage { ) => _makeShaderOptions(tileModeX, tileModeY, filterMode, mipmapMode, matrix?.toJS); @JS('readPixels') - external JSUint8Array? _readPixels(JSNumber srcX, JSNumber srcY, SkImageInfo imageInfo); + external JSUint8Array? _readPixels(double srcX, double srcY, SkImageInfo imageInfo); Uint8List? readPixels(double srcX, double srcY, SkImageInfo imageInfo) => - _readPixels(srcX.toJS, srcY.toJS, imageInfo)?.toDart; + _readPixels(srcX, srcY, imageInfo)?.toDart; @JS('encodeToBytes') external JSUint8Array? _encodeToBytes(); Uint8List? encodeToBytes() => _encodeToBytes()?.toDart; - @JS('isAliasOf') - external JSBoolean _isAliasOf(SkImage other); - bool isAliasOf(SkImage other) => _isAliasOf(other).toDart; + external bool isAliasOf(SkImage other); - @JS('isDeleted') - external JSBoolean _isDeleted(); - bool isDeleted() => _isDeleted().toDart; + external bool isDeleted(); } -@JS() -@staticInterop -class SkShaderNamespace {} - -extension SkShaderNamespaceExtension on SkShaderNamespace { +extension type SkShaderNamespace(JSObject _) implements JSObject { @JS('MakeLinearGradient') external SkShader _MakeLinearGradient( JSFloat32Array from, // 2-element array @@ -1187,12 +838,12 @@ extension SkShaderNamespaceExtension on SkShaderNamespace { @JS('MakeRadialGradient') external SkShader _MakeRadialGradient( JSFloat32Array center, // 2-element array - JSNumber radius, + double radius, JSUint32Array colors, JSFloat32Array colorStops, SkTileMode tileMode, JSFloat32Array? matrix, // 3x3 matrix - JSNumber flags, + double flags, ); SkShader MakeRadialGradient( Float32List center, // 2-element array @@ -1204,25 +855,25 @@ extension SkShaderNamespaceExtension on SkShaderNamespace { double flags, ) => _MakeRadialGradient( center.toJS, - radius.toJS, + radius, colors.toJS, colorStops.toJS, tileMode, matrix?.toJS, - flags.toJS, + flags, ); @JS('MakeTwoPointConicalGradient') external SkShader _MakeTwoPointConicalGradient( JSFloat32Array focal, - JSNumber focalRadius, + double focalRadius, JSFloat32Array center, - JSNumber radius, + double radius, JSUint32Array colors, JSFloat32Array colorStops, SkTileMode tileMode, JSFloat32Array? matrix, // 3x3 matrix - JSNumber flags, + double flags, ); SkShader MakeTwoPointConicalGradient( Float32List focal, @@ -1236,27 +887,27 @@ extension SkShaderNamespaceExtension on SkShaderNamespace { double flags, ) => _MakeTwoPointConicalGradient( focal.toJS, - focalRadius.toJS, + focalRadius, center.toJS, - radius.toJS, + radius, colors.toJS, colorStops.toJS, tileMode, matrix?.toJS, - flags.toJS, + flags, ); @JS('MakeSweepGradient') external SkShader _MakeSweepGradient( - JSNumber cx, - JSNumber cy, + double cx, + double cy, JSUint32Array colors, JSFloat32Array colorStops, SkTileMode tileMode, JSFloat32Array? matrix, // 3x3 matrix - JSNumber flags, - JSNumber startAngle, - JSNumber endAngle, + double flags, + double startAngle, + double endAngle, ); SkShader MakeSweepGradient( double cx, @@ -1269,39 +920,27 @@ extension SkShaderNamespaceExtension on SkShaderNamespace { double startAngle, double endAngle, ) => _MakeSweepGradient( - cx.toJS, - cy.toJS, + cx, + cy, colors.toJS, colorStops.toJS, tileMode, matrix?.toJS, - flags.toJS, - startAngle.toJS, - endAngle.toJS, + flags, + startAngle, + endAngle, ); } -@JS() -@anonymous -@staticInterop -class SkShader {} - -extension SkShaderExtension on SkShader { - external JSVoid delete(); +extension type SkShader(JSObject _) implements JSObject { + external void delete(); } -@JS() -@staticInterop -class SkMaskFilterNamespace {} - -extension SkMaskFilterNamespaceExtension on SkMaskFilterNamespace { +extension type SkMaskFilterNamespace(JSObject _) implements JSObject { // Creates a blur MaskFilter. // // Returns `null` if [sigma] is 0 or infinite. - @JS('MakeBlur') - external SkMaskFilter? _MakeBlur(SkBlurStyle blurStyle, JSNumber sigma, JSBoolean respectCTM); - SkMaskFilter? MakeBlur(SkBlurStyle blurStyle, double sigma, bool respectCTM) => - _MakeBlur(blurStyle, sigma.toJS, respectCTM.toJS); + external SkMaskFilter? MakeBlur(SkBlurStyle blurStyle, double sigma, bool respectCTM); } // This needs to be bound to top-level because SkPaint is initialized @@ -1309,59 +948,32 @@ extension SkMaskFilterNamespaceExtension on SkMaskFilterNamespace { // // external SkPaint SkPaint(); @JS('window.flutterCanvasKit.Paint') -@staticInterop -class SkPaint { - external factory SkPaint(); +extension type SkPaint._(JSObject _) implements JSObject { + external SkPaint(); + + external void setBlendMode(SkBlendMode blendMode); + external void setStyle(SkPaintStyle paintStyle); + external void setStrokeWidth(double width); + external void setStrokeCap(SkStrokeCap cap); + external void setStrokeJoin(SkStrokeJoin join); + external void setAntiAlias(bool isAntiAlias); + external void setColorInt(int color); + external void setShader(SkShader? shader); + external void setMaskFilter(SkMaskFilter? maskFilter); + external void setColorFilter(SkColorFilter? colorFilter); + external void setStrokeMiter(double miterLimit); + external void setImageFilter(SkImageFilter? imageFilter); + external void delete(); } -extension SkPaintExtension on SkPaint { - external JSVoid setBlendMode(SkBlendMode blendMode); - external JSVoid setStyle(SkPaintStyle paintStyle); +extension type CkFilterOptions(JSObject _) implements JSObject {} - @JS('setStrokeWidth') - external JSVoid _setStrokeWidth(JSNumber width); - JSVoid setStrokeWidth(double width) => _setStrokeWidth(width.toJS); - - external JSVoid setStrokeCap(SkStrokeCap cap); - external JSVoid setStrokeJoin(SkStrokeJoin join); - - @JS('setAntiAlias') - external JSVoid _setAntiAlias(JSBoolean isAntiAlias); - void setAntiAlias(bool isAntiAlias) => _setAntiAlias(isAntiAlias.toJS); - - @JS('setColorInt') - external JSVoid _setColorInt(JSNumber color); - void setColorInt(int color) => _setColorInt(color.toJS); - - external JSVoid setShader(SkShader? shader); - external JSVoid setMaskFilter(SkMaskFilter? maskFilter); - external JSVoid setColorFilter(SkColorFilter? colorFilter); - - @JS('setStrokeMiter') - external JSVoid _setStrokeMiter(JSNumber miterLimit); - void setStrokeMiter(double miterLimit) => _setStrokeMiter(miterLimit.toJS); - - external JSVoid setImageFilter(SkImageFilter? imageFilter); - external JSVoid delete(); +extension type _CkCubicFilterOptions._(JSObject _) implements CkFilterOptions { + external _CkCubicFilterOptions({required double B, required double C}); } -@JS() -@anonymous -@staticInterop -abstract class CkFilterOptions {} - -@JS() -@anonymous -@staticInterop -class _CkCubicFilterOptions extends CkFilterOptions { - external factory _CkCubicFilterOptions({required JSNumber B, required JSNumber C}); -} - -@JS() -@anonymous -@staticInterop -class _CkTransformFilterOptions extends CkFilterOptions { - external factory _CkTransformFilterOptions({SkFilterMode filter, SkMipmapMode mipmap}); +extension type _CkTransformFilterOptions._(JSObject _) implements CkFilterOptions { + external _CkTransformFilterOptions({SkFilterMode filter, SkMipmapMode mipmap}); } final Map _filterOptions = { @@ -1377,27 +989,18 @@ final Map _filterOptions = @@ -1416,39 +1019,23 @@ extension SkColorFilterNamespaceExtension on SkColorFilterNamespace { external SkColorFilter MakeCompose(SkColorFilter? outer, SkColorFilter inner); } -@JS() -@anonymous -@staticInterop -class SkColorFilter {} - -extension SkColorFilterExtension on SkColorFilter { - external JSVoid delete(); +extension type SkColorFilter(JSObject _) implements JSObject { + external void delete(); } -@JS() -@staticInterop -class SkImageFilterNamespace {} - -extension SkImageFilterNamespaceExtension on SkImageFilterNamespace { - @JS('MakeBlur') - external SkImageFilter _MakeBlur( - JSNumber sigmaX, - JSNumber sigmaY, - SkTileMode tileMode, - JSVoid input, // we don't use this yet - ); - SkImageFilter MakeBlur( +extension type SkImageFilterNamespace(JSObject _) implements JSObject { + external SkImageFilter MakeBlur( double sigmaX, double sigmaY, SkTileMode tileMode, void input, // we don't use this yet - ) => _MakeBlur(sigmaX.toJS, sigmaY.toJS, tileMode, input); + ); @JS('MakeMatrixTransform') external SkImageFilter _MakeMatrixTransform( JSFloat32Array matrix, // 3x3 matrix CkFilterOptions filterOptions, - JSVoid input, // we don't use this yet + void input, // we don't use this yet ); SkImageFilter MakeMatrixTransform( Float32List matrix, // 3x3 matrix @@ -1458,7 +1045,7 @@ extension SkImageFilterNamespaceExtension on SkImageFilterNamespace { external SkImageFilter MakeColorFilter( SkColorFilter colorFilter, - JSVoid input, // we don't use this yet + void input, // we don't use this yet ); external SkImageFilter MakeCompose(SkImageFilter outer, SkImageFilter inner); @@ -1476,28 +1063,17 @@ extension SkImageFilterNamespaceExtension on SkImageFilterNamespace { ); } -@JS() -@anonymous -@staticInterop -class SkImageFilter {} +extension type SkImageFilter(JSObject _) implements JSObject { + external void delete(); -extension SkImageFilterExtension on SkImageFilter { - external JSVoid delete(); - - @JS('isDeleted') - external JSBoolean _isDeleted(); - bool isDeleted() => _isDeleted().toDart; + external bool isDeleted(); @JS('getOutputBounds') external JSInt32Array _getOutputBounds(JSFloat32Array bounds); Int32List getOutputBounds(Float32List bounds) => _getOutputBounds(bounds.toJS).toDart; } -@JS() -@staticInterop -class SkPathNamespace {} - -extension SkPathNamespaceExtension on SkPathNamespace { +extension type SkPathNamespace(JSObject _) implements JSObject { /// Creates an [SkPath] using commands obtained from [SkPath.toCmds]. @JS('MakeFromCmds') external SkPath _MakeFromCmds(JSAny pathCommands); @@ -1589,9 +1165,7 @@ Float32List toSkColorStops(List? colorStops) { return skColorStops; } -@JS() -@staticInterop -abstract class _NativeType {} +extension type _NativeType(JSObject _) implements JSObject {} @JS('Float32Array') external _NativeType get _nativeFloat32ArrayType; @@ -1600,14 +1174,14 @@ external _NativeType get _nativeFloat32ArrayType; external _NativeType get _nativeUint32ArrayType; @JS('window.flutterCanvasKit.Malloc') -external JSAny _malloc(_NativeType nativeType, JSNumber length); +external JSAny _malloc(_NativeType nativeType, int length); /// Allocates a [Float32List] of [length] elements, backed by WASM memory, /// managed by a [SkFloat32List]. /// /// To free the allocated array use [free]. SkFloat32List mallocFloat32List(int length) { - return _malloc(_nativeFloat32ArrayType, length.toJS) as SkFloat32List; + return _malloc(_nativeFloat32ArrayType, length) as SkFloat32List; } /// Allocates a [Uint32List] of [length] elements, backed by WASM memory, @@ -1615,7 +1189,7 @@ SkFloat32List mallocFloat32List(int length) { /// /// To free the allocated array use [free]. SkUint32List mallocUint32List(int length) { - return _malloc(_nativeUint32ArrayType, length.toJS) as SkUint32List; + return _malloc(_nativeUint32ArrayType, length) as SkUint32List; } /// Frees the WASM memory occupied by a [SkFloat32List] or [SkUint32List]. @@ -1624,30 +1198,18 @@ SkUint32List mallocUint32List(int length) { /// /// Use this function to free lists owned by the engine. @JS('window.flutterCanvasKit.Free') -external JSVoid free(MallocObj list); +external void free(MallocObj list); -@JS() -@staticInterop -abstract class MallocObj {} +extension type MallocObj(JSObject _) implements JSObject {} /// Wraps a [Float32List] backed by WASM memory. /// /// This wrapper is necessary because the raw [Float32List] will get detached /// when WASM grows its memory. Call [toTypedArray] to get a new instance /// that's attached to the current WASM memory block. -@JS() -@staticInterop -class SkFloat32List extends MallocObj {} - -extension SkFloat32ListExtension on SkFloat32List { +extension type SkFloat32List(JSObject _) implements MallocObj { /// The number of objects this pointer refers to. - @JS('length') - external JSNumber get _length; - double get length => _length.toDartDouble; - - @JS('length') - external set _length(JSNumber length); - set length(double l) => _length = l.toJS; + external double length; /// Returns the [Float32List] object backed by WASM memory. /// @@ -1666,19 +1228,9 @@ extension SkFloat32ListExtension on SkFloat32List { /// This wrapper is necessary because the raw [Uint32List] will get detached /// when WASM grows its memory. Call [toTypedArray] to get a new instance /// that's attached to the current WASM memory block. -@JS() -@staticInterop -class SkUint32List extends MallocObj {} - -extension SkUint32ListExtension on SkUint32List { +extension type SkUint32List(JSObject _) implements MallocObj { /// The number of objects this pointer refers to. - @JS('length') - external JSNumber get _length; - double get length => _length.toDartDouble; - - @JS('length') - external set _length(JSNumber length); - set length(double l) => _length = l.toJS; + external double length; /// Returns the [Uint32List] object backed by WASM memory. /// @@ -1736,44 +1288,23 @@ Float32List toSharedSkColor3(ui.Color color) { final SkFloat32List _sharedSkColor3 = mallocFloat32List(4); @JS('window.flutterCanvasKit.Path') -@staticInterop -class SkPath { - external factory SkPath(); - external factory SkPath.from(SkPath other); -} +extension type SkPath._(JSObject _) implements JSObject { + external SkPath(); + external SkPath.from(SkPath other); -extension SkPathExtension on SkPath { - external JSVoid setFillType(SkFillType fillType); + external void setFillType(SkFillType fillType); @JS('addArc') - external JSVoid _addArc( - JSFloat32Array oval, - JSNumber startAngleDegrees, - JSNumber sweepAngleDegrees, - ); + external void _addArc(JSFloat32Array oval, double startAngleDegrees, double sweepAngleDegrees); void addArc(Float32List oval, double startAngleDegrees, double sweepAngleDegrees) => - _addArc(oval.toJS, startAngleDegrees.toJS, sweepAngleDegrees.toJS); + _addArc(oval.toJS, startAngleDegrees, sweepAngleDegrees); @JS('addOval') - external JSVoid _addOval(JSFloat32Array oval, JSBoolean counterClockWise, JSNumber startIndex); + external void _addOval(JSFloat32Array oval, bool counterClockWise, double startIndex); void addOval(Float32List oval, bool counterClockWise, double startIndex) => - _addOval(oval.toJS, counterClockWise.toJS, startIndex.toJS); + _addOval(oval.toJS, counterClockWise, startIndex); - @JS('addPath') - external JSVoid _addPath( - SkPath other, - JSNumber scaleX, - JSNumber skewX, - JSNumber transX, - JSNumber skewY, - JSNumber scaleY, - JSNumber transY, - JSNumber pers0, - JSNumber pers1, - JSNumber pers2, - JSBoolean extendPath, - ); - void addPath( + external void addPath( SkPath other, double scaleX, double skewX, @@ -1785,58 +1316,36 @@ extension SkPathExtension on SkPath { double pers1, double pers2, bool extendPath, - ) => _addPath( - other, - scaleX.toJS, - skewX.toJS, - transX.toJS, - skewY.toJS, - scaleY.toJS, - transY.toJS, - pers0.toJS, - pers1.toJS, - pers2.toJS, - extendPath.toJS, ); @JS('addPoly') - external JSVoid _addPoly(JSFloat32Array points, JSBoolean close); - void addPoly(Float32List points, bool close) => _addPoly(points.toJS, close.toJS); + external void _addPoly(JSFloat32Array points, bool close); + void addPoly(Float32List points, bool close) => _addPoly(points.toJS, close); @JS('addRRect') - external JSVoid _addRRect(JSFloat32Array rrect, JSBoolean counterClockWise); + external void _addRRect(JSFloat32Array rrect, bool counterClockWise); void addRRect(Float32List rrect, bool counterClockWise) => - _addRRect(rrect.toJS, counterClockWise.toJS); + _addRRect(rrect.toJS, counterClockWise); @JS('addRect') - external JSVoid _addRect(JSFloat32Array rect); + external void _addRect(JSFloat32Array rect); void addRect(Float32List rect) => _addRect(rect.toJS); @JS('arcToOval') - external JSVoid _arcToOval( + external void _arcToOval( JSFloat32Array oval, - JSNumber startAngleDegrees, - JSNumber sweepAngleDegrees, - JSBoolean forceMoveTo, + double startAngleDegrees, + double sweepAngleDegrees, + bool forceMoveTo, ); void arcToOval( Float32List oval, double startAngleDegrees, double sweepAngleDegrees, bool forceMoveTo, - ) => _arcToOval(oval.toJS, startAngleDegrees.toJS, sweepAngleDegrees.toJS, forceMoveTo.toJS); + ) => _arcToOval(oval.toJS, startAngleDegrees, sweepAngleDegrees, forceMoveTo); - @JS('arcToRotated') - external JSVoid _arcToRotated( - JSNumber radiusX, - JSNumber radiusY, - JSNumber rotation, - JSBoolean useSmallArc, - JSBoolean counterClockWise, - JSNumber x, - JSNumber y, - ); - void arcToRotated( + external void arcToRotated( double radiusX, double radiusY, double rotation, @@ -1844,67 +1353,21 @@ extension SkPathExtension on SkPath { bool counterClockWise, double x, double y, - ) => _arcToRotated( - radiusX.toJS, - radiusY.toJS, - rotation.toJS, - useSmallArc.toJS, - counterClockWise.toJS, - x.toJS, - y.toJS, ); - external JSVoid close(); - - @JS('conicTo') - external JSVoid _conicTo(JSNumber x1, JSNumber y1, JSNumber x2, JSNumber y2, JSNumber w); - void conicTo(double x1, double y1, double x2, double y2, double w) => - _conicTo(x1.toJS, y1.toJS, x2.toJS, y2.toJS, w.toJS); - - @JS('contains') - external JSBoolean _contains(JSNumber x, JSNumber y); - bool contains(double x, double y) => _contains(x.toJS, y.toJS).toDart; - - @JS('cubicTo') - external JSVoid _cubicTo( - JSNumber x1, - JSNumber y1, - JSNumber x2, - JSNumber y2, - JSNumber x3, - JSNumber y3, - ); - void cubicTo(double x1, double y1, double x2, double y2, double x3, double y3) => - _cubicTo(x1.toJS, y1.toJS, x2.toJS, y2.toJS, x3.toJS, y3.toJS); + external void close(); + external void conicTo(double x1, double y1, double x2, double y2, double w); + external bool contains(double x, double y); + external void cubicTo(double x1, double y1, double x2, double y2, double x3, double y3); @JS('getBounds') external JSFloat32Array _getBounds(); Float32List getBounds() => _getBounds().toDart; - @JS('lineTo') - external JSVoid _lineTo(JSNumber x, JSNumber y); - void lineTo(double x, double y) => _lineTo(x.toJS, y.toJS); - - @JS('moveTo') - external JSVoid _moveTo(JSNumber x, JSNumber y); - void moveTo(double x, double y) => _moveTo(x.toJS, y.toJS); - - @JS('quadTo') - external JSVoid _quadTo(JSNumber x1, JSNumber y1, JSNumber x2, JSNumber y2); - void quadTo(double x1, double y1, double x2, double y2) => - _quadTo(x1.toJS, y1.toJS, x2.toJS, y2.toJS); - - @JS('rArcTo') - external JSVoid _rArcTo( - JSNumber x, - JSNumber y, - JSNumber rotation, - JSBoolean useSmallArc, - JSBoolean counterClockWise, - JSNumber deltaX, - JSNumber deltaY, - ); - void rArcTo( + external void lineTo(double x, double y); + external void moveTo(double x, double y); + external void quadTo(double x1, double y1, double x2, double y2); + external void rArcTo( double x, double y, double rotation, @@ -1912,71 +1375,17 @@ extension SkPathExtension on SkPath { bool counterClockWise, double deltaX, double deltaY, - ) => _rArcTo( - x.toJS, - y.toJS, - rotation.toJS, - useSmallArc.toJS, - counterClockWise.toJS, - deltaX.toJS, - deltaY.toJS, ); - - @JS('rConicTo') - external JSVoid _rConicTo(JSNumber x1, JSNumber y1, JSNumber x2, JSNumber y2, JSNumber w); - void rConicTo(double x1, double y1, double x2, double y2, double w) => - _rConicTo(x1.toJS, y1.toJS, x2.toJS, y2.toJS, w.toJS); - - @JS('rCubicTo') - external JSVoid _rCubicTo( - JSNumber x1, - JSNumber y1, - JSNumber x2, - JSNumber y2, - JSNumber x3, - JSNumber y3, - ); - void rCubicTo(double x1, double y1, double x2, double y2, double x3, double y3) => - _rCubicTo(x1.toJS, y1.toJS, x2.toJS, y2.toJS, x3.toJS, y3.toJS); - - @JS('rLineTo') - external JSVoid _rLineTo(JSNumber x, JSNumber y); - void rLineTo(double x, double y) => _rLineTo(x.toJS, y.toJS); - - @JS('rMoveTo') - external JSVoid _rMoveTo(JSNumber x, JSNumber y); - void rMoveTo(double x, double y) => _rMoveTo(x.toJS, y.toJS); - - @JS('rQuadTo') - external JSVoid _rQuadTo(JSNumber x1, JSNumber y1, JSNumber x2, JSNumber y2); - void rQuadTo(double x1, double y1, double x2, double y2) => - _rQuadTo(x1.toJS, y1.toJS, x2.toJS, y2.toJS); - - external JSVoid reset(); - - @JS('toSVGString') - external JSString _toSVGString(); - String toSVGString() => _toSVGString().toDart; - - @JS('isEmpty') - external JSBoolean _isEmpty(); - bool isEmpty() => _isEmpty().toDart; - + external void rConicTo(double x1, double y1, double x2, double y2, double w); + external void rCubicTo(double x1, double y1, double x2, double y2, double x3, double y3); + external void rLineTo(double x, double y); + external void rMoveTo(double x, double y); + external void rQuadTo(double x1, double y1, double x2, double y2); + external void reset(); + external String toSVGString(); + external bool isEmpty(); external SkPath copy(); - - @JS('transform') - external JSVoid _transform( - JSNumber scaleX, - JSNumber skewX, - JSNumber transX, - JSNumber skewY, - JSNumber scaleY, - JSNumber transY, - JSNumber pers0, - JSNumber pers1, - JSNumber pers2, - ); - void transform( + external void transform( double scaleX, double skewX, double transX, @@ -1986,16 +1395,6 @@ extension SkPathExtension on SkPath { double pers0, double pers1, double pers2, - ) => _transform( - scaleX.toJS, - skewX.toJS, - transX.toJS, - skewY.toJS, - scaleY.toJS, - transY.toJS, - pers0.toJS, - pers1.toJS, - pers2.toJS, ); /// Serializes the path into a list of commands. @@ -2006,45 +1405,27 @@ extension SkPathExtension on SkPath { external JSAny _toCmds(); List toCmds() => _toCmds().toObjectShallow as List; - external JSVoid delete(); + external void delete(); } @JS('window.flutterCanvasKit.ContourMeasureIter') -@staticInterop -class SkContourMeasureIter { - factory SkContourMeasureIter(SkPath path, bool forceClosed, double resScale) => - SkContourMeasureIter._(path, forceClosed.toJS, resScale.toJS); - external factory SkContourMeasureIter._(SkPath path, JSBoolean forceClosed, JSNumber resScale); -} +extension type SkContourMeasureIter._(JSObject _) implements JSObject { + external SkContourMeasureIter(SkPath path, bool forceClosed, double resScale); -extension SkContourMeasureIterExtension on SkContourMeasureIter { external SkContourMeasure? next(); - external JSVoid delete(); + external void delete(); } -@JS() -@staticInterop -class SkContourMeasure {} - -extension SkContourMeasureExtension on SkContourMeasure { - @JS('getSegment') - external SkPath _getSegment(JSNumber start, JSNumber end, JSBoolean startWithMoveTo); - SkPath getSegment(double start, double end, bool startWithMoveTo) => - _getSegment(start.toJS, end.toJS, startWithMoveTo.toJS); +extension type SkContourMeasure(JSObject _) implements JSObject { + external SkPath getSegment(double start, double end, bool startWithMoveTo); @JS('getPosTan') - external JSFloat32Array _getPosTan(JSNumber distance); - Float32List getPosTan(double distance) => _getPosTan(distance.toJS).toDart; + external JSFloat32Array _getPosTan(double distance); + Float32List getPosTan(double distance) => _getPosTan(distance).toDart; - @JS('isClosed') - external JSBoolean _isClosed(); - bool isClosed() => _isClosed().toDart; - - @JS('length') - external JSNumber _length(); - double length() => _length().toDartDouble; - - external JSVoid delete(); + external bool isClosed(); + external double length(); + external void delete(); } // TODO(hterkelsen): Use a shared malloc'ed array for performance. @@ -2146,18 +1527,15 @@ Uint16List toUint16List(List ints) { } @JS('window.flutterCanvasKit.PictureRecorder') -@staticInterop -class SkPictureRecorder { - external factory SkPictureRecorder(); -} +extension type SkPictureRecorder._(JSObject _) implements JSObject { + external SkPictureRecorder(); -extension SkPictureRecorderExtension on SkPictureRecorder { @JS('beginRecording') - external SkCanvas _beginRecording(JSFloat32Array bounds, JSBoolean computeBounds); - SkCanvas beginRecording(Float32List bounds) => _beginRecording(bounds.toJS, true.toJS); + external SkCanvas _beginRecording(JSFloat32Array bounds, bool computeBounds); + SkCanvas beginRecording(Float32List bounds) => _beginRecording(bounds.toJS, true); external SkPicture finishRecordingAsPicture(); - external JSVoid delete(); + external void delete(); } /// We do not use the `delete` method (which may be removed in the future anyway). @@ -2165,41 +1543,36 @@ extension SkPictureRecorderExtension on SkPictureRecorder { /// By Skia coding convention raw pointers should always be treated as /// "borrowed", i.e. their memory is managed by other objects. In the case of /// [SkCanvas] it is managed by [SkPictureRecorder]. -@JS() -@anonymous -@staticInterop -class SkCanvas {} - -extension SkCanvasExtension on SkCanvas { +extension type SkCanvas(JSObject _) implements JSObject { @JS('clear') - external JSVoid _clear(JSFloat32Array color); + external void _clear(JSFloat32Array color); void clear(Float32List color) => _clear(color.toJS); @JS('clipPath') - external JSVoid _clipPath(SkPath path, SkClipOp clipOp, JSBoolean doAntiAlias); + external void _clipPath(SkPath path, SkClipOp clipOp, bool doAntiAlias); void clipPath(SkPath path, SkClipOp clipOp, bool doAntiAlias) => - _clipPath(path, clipOp, doAntiAlias.toJS); + _clipPath(path, clipOp, doAntiAlias); @JS('clipRRect') - external JSVoid _clipRRect(JSFloat32Array rrect, SkClipOp clipOp, JSBoolean doAntiAlias); + external void _clipRRect(JSFloat32Array rrect, SkClipOp clipOp, bool doAntiAlias); void clipRRect(Float32List rrect, SkClipOp clipOp, bool doAntiAlias) => - _clipRRect(rrect.toJS, clipOp, doAntiAlias.toJS); + _clipRRect(rrect.toJS, clipOp, doAntiAlias); @JS('clipRect') - external JSVoid _clipRect(JSFloat32Array rect, SkClipOp clipOp, JSBoolean doAntiAlias); + external void _clipRect(JSFloat32Array rect, SkClipOp clipOp, bool doAntiAlias); void clipRect(Float32List rect, SkClipOp clipOp, bool doAntiAlias) => - _clipRect(rect.toJS, clipOp, doAntiAlias.toJS); + _clipRect(rect.toJS, clipOp, doAntiAlias); @JS('getDeviceClipBounds') external JSInt32Array _getDeviceClipBounds(); Int32List getDeviceClipBounds() => _getDeviceClipBounds().toDart; @JS('drawArc') - external JSVoid _drawArc( + external void _drawArc( JSFloat32Array oval, - JSNumber startAngleDegrees, - JSNumber sweepAngleDegrees, - JSBoolean useCenter, + double startAngleDegrees, + double sweepAngleDegrees, + bool useCenter, SkPaint paint, ); void drawArc( @@ -2208,10 +1581,10 @@ extension SkCanvasExtension on SkCanvas { double sweepAngleDegrees, bool useCenter, SkPaint paint, - ) => _drawArc(oval.toJS, startAngleDegrees.toJS, sweepAngleDegrees.toJS, useCenter.toJS, paint); + ) => _drawArc(oval.toJS, startAngleDegrees, sweepAngleDegrees, useCenter, paint); @JS('drawAtlas') - external JSVoid _drawAtlas( + external void _drawAtlas( SkImage image, JSFloat32Array rects, JSFloat32Array rstTransforms, @@ -2228,57 +1601,39 @@ extension SkCanvasExtension on SkCanvas { Uint32List? colors, ) => _drawAtlas(image, rects.toJS, rstTransforms.toJS, paint, blendMode, colors?.toJS); - @JS('drawCircle') - external JSVoid _drawCircle(JSNumber x, JSNumber y, JSNumber radius, SkPaint paint); - void drawCircle(double x, double y, double radius, SkPaint paint) => - _drawCircle(x.toJS, y.toJS, radius.toJS, paint); - - @JS('drawColorInt') - external JSVoid _drawColorInt(JSNumber color, SkBlendMode blendMode); - void drawColorInt(double color, SkBlendMode blendMode) => _drawColorInt(color.toJS, blendMode); + external void drawCircle(double x, double y, double radius, SkPaint paint); + external void drawColorInt(double color, SkBlendMode blendMode); @JS('drawDRRect') - external JSVoid _drawDRRect(JSFloat32Array outer, JSFloat32Array inner, SkPaint paint); + external void _drawDRRect(JSFloat32Array outer, JSFloat32Array inner, SkPaint paint); void drawDRRect(Float32List outer, Float32List inner, SkPaint paint) => _drawDRRect(outer.toJS, inner.toJS, paint); - @JS('drawImageCubic') - external JSVoid _drawImageCubic( + external void drawImageCubic( SkImage image, - JSNumber x, - JSNumber y, - JSNumber B, - JSNumber C, + double x, + double y, + double B, + double C, SkPaint paint, ); - void drawImageCubic(SkImage image, double x, double y, double B, double C, SkPaint paint) => - _drawImageCubic(image, x.toJS, y.toJS, B.toJS, C.toJS, paint); - @JS('drawImageOptions') - external JSVoid _drawImageOptions( - SkImage image, - JSNumber x, - JSNumber y, - SkFilterMode filterMode, - SkMipmapMode mipmapMode, - SkPaint paint, - ); - void drawImageOptions( + external void drawImageOptions( SkImage image, double x, double y, SkFilterMode filterMode, SkMipmapMode mipmapMode, SkPaint paint, - ) => _drawImageOptions(image, x.toJS, y.toJS, filterMode, mipmapMode, paint); + ); @JS('drawImageRectCubic') - external JSVoid _drawImageRectCubic( + external void _drawImageRectCubic( SkImage image, JSFloat32Array src, JSFloat32Array dst, - JSNumber B, - JSNumber C, + double B, + double C, SkPaint paint, ); void drawImageRectCubic( @@ -2288,10 +1643,10 @@ extension SkCanvasExtension on SkCanvas { double B, double C, SkPaint paint, - ) => _drawImageRectCubic(image, src.toJS, dst.toJS, B.toJS, C.toJS, paint); + ) => _drawImageRectCubic(image, src.toJS, dst.toJS, B, C, paint); @JS('drawImageRectOptions') - external JSVoid _drawImageRectOptions( + external void _drawImageRectOptions( SkImage image, JSFloat32Array src, JSFloat32Array dst, @@ -2309,7 +1664,7 @@ extension SkCanvasExtension on SkCanvas { ) => _drawImageRectOptions(image, src.toJS, dst.toJS, filterMode, mipmapMode, paint); @JS('drawImageNine') - external JSVoid _drawImageNine( + external void _drawImageNine( SkImage image, JSFloat32Array center, JSFloat32Array dst, @@ -2324,40 +1679,37 @@ extension SkCanvasExtension on SkCanvas { SkPaint paint, ) => _drawImageNine(image, center.toJS, dst.toJS, filterMode, paint); - @JS('drawLine') - external JSVoid _drawLine(JSNumber x1, JSNumber y1, JSNumber x2, JSNumber y2, SkPaint paint); - void drawLine(double x1, double y1, double x2, double y2, SkPaint paint) => - _drawLine(x1.toJS, y1.toJS, x2.toJS, y2.toJS, paint); + external void drawLine(double x1, double y1, double x2, double y2, SkPaint paint); @JS('drawOval') - external JSVoid _drawOval(JSFloat32Array rect, SkPaint paint); + external void _drawOval(JSFloat32Array rect, SkPaint paint); void drawOval(Float32List rect, SkPaint paint) => _drawOval(rect.toJS, paint); - external JSVoid drawPaint(SkPaint paint); - external JSVoid drawPath(SkPath path, SkPaint paint); + external void drawPaint(SkPaint paint); + external void drawPath(SkPath path, SkPaint paint); @JS('drawPoints') - external JSVoid _drawPoints(SkPointMode pointMode, JSFloat32Array points, SkPaint paint); + external void _drawPoints(SkPointMode pointMode, JSFloat32Array points, SkPaint paint); void drawPoints(SkPointMode pointMode, Float32List points, SkPaint paint) => _drawPoints(pointMode, points.toJS, paint); @JS('drawRRect') - external JSVoid _drawRRect(JSFloat32Array rrect, SkPaint paint); + external void _drawRRect(JSFloat32Array rrect, SkPaint paint); void drawRRect(Float32List rrect, SkPaint paint) => _drawRRect(rrect.toJS, paint); @JS('drawRect') - external JSVoid _drawRect(JSFloat32Array rect, SkPaint paint); + external void _drawRect(JSFloat32Array rect, SkPaint paint); void drawRect(Float32List rect, SkPaint paint) => _drawRect(rect.toJS, paint); @JS('drawShadow') - external JSVoid _drawShadow( + external void _drawShadow( SkPath path, JSFloat32Array zPlaneParams, JSFloat32Array lightPos, - JSNumber lightRadius, + double lightRadius, JSFloat32Array ambientColor, JSFloat32Array spotColor, - JSNumber flags, + double flags, ); void drawShadow( SkPath path, @@ -2371,28 +1723,22 @@ extension SkCanvasExtension on SkCanvas { path, zPlaneParams.toJS, lightPos.toJS, - lightRadius.toJS, + lightRadius, ambientColor.toJS, spotColor.toJS, - flags.toJS, + flags, ); - external JSVoid drawVertices(SkVertices vertices, SkBlendMode blendMode, SkPaint paint); - - @JS('save') - external JSNumber _save(); - double save() => _save().toDartDouble; - - @JS('getSaveCount') - external JSNumber _getSaveCount(); - double getSaveCount() => _getSaveCount().toDartDouble; + external void drawVertices(SkVertices vertices, SkBlendMode blendMode, SkPaint paint); + external double save(); + external double getSaveCount(); @JS('saveLayer') - external JSVoid _saveLayer( + external void _saveLayer( SkPaint? paint, JSFloat32Array? bounds, SkImageFilter? backdrop, - JSNumber? flags, + int? flags, SkTileMode backdropTileMode, ); void saveLayer( @@ -2401,74 +1747,43 @@ extension SkCanvasExtension on SkCanvas { SkImageFilter? backdrop, int? flags, SkTileMode backdropTileMode, - ) => _saveLayer(paint, bounds?.toJS, backdrop, flags?.toJS, backdropTileMode); + ) => _saveLayer(paint, bounds?.toJS, backdrop, flags, backdropTileMode); - external JSVoid restore(); - - @JS('restoreToCount') - external JSVoid _restoreToCount(JSNumber count); - void restoreToCount(double count) => _restoreToCount(count.toJS); - - @JS('rotate') - external JSVoid _rotate(JSNumber angleDegrees, JSNumber px, JSNumber py); - void rotate(double angleDegrees, double px, double py) => - _rotate(angleDegrees.toJS, px.toJS, py.toJS); - - @JS('scale') - external JSVoid _scale(JSNumber x, JSNumber y); - void scale(double x, double y) => _scale(x.toJS, y.toJS); - - @JS('skew') - external JSVoid _skew(JSNumber x, JSNumber y); - void skew(double x, double y) => _skew(x.toJS, y.toJS); + external void restore(); + external void restoreToCount(double count); + external void rotate(double angleDegrees, double px, double py); + external void scale(double x, double y); + external void skew(double x, double y); @JS('concat') - external JSVoid _concat(JSFloat32Array matrix); + external void _concat(JSFloat32Array matrix); void concat(Float32List matrix) => _concat(matrix.toJS); - @JS('translate') - external JSVoid _translate(JSNumber x, JSNumber y); - void translate(double x, double y) => _translate(x.toJS, y.toJS); + external void translate(double x, double y); @JS('getLocalToDevice') external JSAny _getLocalToDevice(); List getLocalToDevice() => _getLocalToDevice().toObjectShallow as List; @JS('quickReject') - external JSBoolean _quickReject(JSFloat32Array rect); - bool quickReject(Float32List rect) => _quickReject(rect.toJS).toDart; + external bool _quickReject(JSFloat32Array rect); + bool quickReject(Float32List rect) => _quickReject(rect.toJS); - external JSVoid drawPicture(SkPicture picture); - - @JS('drawParagraph') - external JSVoid _drawParagraph(SkParagraph paragraph, JSNumber x, JSNumber y); - void drawParagraph(SkParagraph paragraph, double x, double y) => - _drawParagraph(paragraph, x.toJS, y.toJS); + external void drawPicture(SkPicture picture); + external void drawParagraph(SkParagraph paragraph, double x, double y); } -@JS() -@anonymous -@staticInterop -class SkPicture {} - -extension SkPictureExtension on SkPicture { - external JSVoid delete(); +extension type SkPicture(JSObject _) implements JSObject { + external void delete(); @JS('cullRect') external JSFloat32Array _cullRect(); Float32List cullRect() => _cullRect().toDart; - @JS('approximateBytesUsed') - external JSNumber _approximateBytesUsed(); - int approximateBytesUsed() => _approximateBytesUsed().toDartInt; + external int approximateBytesUsed(); } -@JS() -@anonymous -@staticInterop -class SkParagraphBuilderNamespace {} - -extension SkParagraphBuilderNamespaceExtension on SkParagraphBuilderNamespace { +extension type SkParagraphBuilderNamespace(JSObject _) implements JSObject { external SkParagraphBuilder MakeFromFontCollection( SkParagraphStyle paragraphStyle, SkFontCollection? fontCollection, @@ -2482,120 +1797,72 @@ extension SkParagraphBuilderNamespaceExtension on SkParagraphBuilderNamespace { } } -@JS() -@anonymous -@staticInterop -class SkParagraphBuilder {} - -extension SkParagraphBuilderExtension on SkParagraphBuilder { - @JS('addText') - external JSVoid _addText(JSString text); - void addText(String text) => _addText(text.toJS); - - external JSVoid pushStyle(SkTextStyle textStyle); - external JSVoid pushPaintStyle(SkTextStyle textStyle, SkPaint foreground, SkPaint background); - external JSVoid pop(); - - @JS('addPlaceholder') - external JSVoid _addPlaceholder( - JSNumber width, - JSNumber height, - SkPlaceholderAlignment alignment, - SkTextBaseline baseline, - JSNumber offset, - ); - void addPlaceholder( +extension type SkParagraphBuilder(JSObject _) implements JSObject { + external void addText(String text); + external void pushStyle(SkTextStyle textStyle); + external void pushPaintStyle(SkTextStyle textStyle, SkPaint foreground, SkPaint background); + external void pop(); + external void addPlaceholder( double width, double height, SkPlaceholderAlignment alignment, SkTextBaseline baseline, double offset, - ) => _addPlaceholder(width.toJS, height.toJS, alignment, baseline, offset.toJS); + ); @JS('getText') - external JSString _getTextUtf8(); - String getTextUtf8() => _getTextUtf8().toDart; + external String getTextUtf8(); // SkParagraphBuilder.getText() returns a utf8 string, we need to decode it // into a utf16 string. String getText() => utf8.decode(getTextUtf8().codeUnits); @JS('setWordsUtf8') - external JSVoid _setWordsUtf8(JSUint32Array words); + external void _setWordsUtf8(JSUint32Array words); void setWordsUtf8(Uint32List words) => _setWordsUtf8(words.toJS); @JS('setWordsUtf16') - external JSVoid _setWordsUtf16(JSUint32Array words); + external void _setWordsUtf16(JSUint32Array words); void setWordsUtf16(Uint32List words) => _setWordsUtf16(words.toJS); @JS('setGraphemeBreaksUtf8') - external JSVoid _setGraphemeBreaksUtf8(JSUint32Array graphemes); + external void _setGraphemeBreaksUtf8(JSUint32Array graphemes); void setGraphemeBreaksUtf8(Uint32List graphemes) => _setGraphemeBreaksUtf8(graphemes.toJS); @JS('setGraphemeBreaksUtf16') - external JSVoid _setGraphemeBreaksUtf16(JSUint32Array graphemes); + external void _setGraphemeBreaksUtf16(JSUint32Array graphemes); void setGraphemeBreaksUtf16(Uint32List graphemes) => _setGraphemeBreaksUtf16(graphemes.toJS); @JS('setLineBreaksUtf8') - external JSVoid _setLineBreaksUtf8(JSUint32Array lineBreaks); + external void _setLineBreaksUtf8(JSUint32Array lineBreaks); void setLineBreaksUtf8(Uint32List lineBreaks) => _setLineBreaksUtf8(lineBreaks.toJS); @JS('setLineBreaksUtf16') - external JSVoid _setLineBreaksUtf16(JSUint32Array lineBreaks); + external void _setLineBreaksUtf16(JSUint32Array lineBreaks); void setLineBreaksUtf16(Uint32List lineBreaks) => _setLineBreaksUtf16(lineBreaks.toJS); external SkParagraph build(); - external JSVoid delete(); + external void delete(); } -@JS() -@anonymous -@staticInterop -class SkParagraphStyle {} +extension type SkParagraphStyle(JSObject _) implements JSObject {} -@JS() -@anonymous -@staticInterop -class SkParagraphStyleProperties { - external factory SkParagraphStyleProperties(); -} - -extension SkParagraphStylePropertiesExtension on SkParagraphStyleProperties { +extension type SkParagraphStyleProperties._(JSObject _) implements JSObject { + external SkParagraphStyleProperties({int dummyArgumentToCreateObjectLiteral}); external set textAlign(SkTextAlign? value); external set textDirection(SkTextDirection? value); - - @JS('heightMultiplier') - external set _heightMultiplier(JSNumber? value); - set heightMultiplier(double? value) => _heightMultiplier = value?.toJS; - + external set heightMultiplier(double? value); external set textHeightBehavior(SkTextHeightBehavior? value); - - @JS('maxLines') - external set _maxLines(JSNumber? value); - set maxLines(int? value) => _maxLines = value?.toJS; - - @JS('ellipsis') - external set _ellipsis(JSString? value); - set ellipsis(String? value) => _ellipsis = value?.toJS; - + external set maxLines(int? value); + external set ellipsis(String? value); external set textStyle(SkTextStyleProperties? value); external set strutStyle(SkStrutStyleProperties? strutStyle); - - @JS('replaceTabCharacters') - external set _replaceTabCharacters(JSBoolean? bool); - set replaceTabCharacters(bool? bool) => _replaceTabCharacters = bool?.toJS; - + external set replaceTabCharacters(bool? bool); external set applyRoundingHack(bool applyRoundingHack); } -@JS() -@staticInterop -class SkTextStyle {} +extension type SkTextStyle(JSObject _) implements JSObject {} -@JS() -@staticInterop -class SkTextDecorationStyleEnum {} - -extension SkTextDecorationStyleEnumExtension on SkTextDecorationStyleEnum { +extension type SkTextDecorationStyleEnum(JSObject _) implements JSObject { external SkTextDecorationStyle get Solid; external SkTextDecorationStyle get Double; external SkTextDecorationStyle get Dotted; @@ -2603,14 +1870,8 @@ extension SkTextDecorationStyleEnumExtension on SkTextDecorationStyleEnum { external SkTextDecorationStyle get Wavy; } -@JS() -@staticInterop -class SkTextDecorationStyle {} - -extension SkTextDecorationStyleExtension on SkTextDecorationStyle { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkTextDecorationStyle(JSObject _) implements JSObject { + external double get value; } final List _skTextDecorationStyles = [ @@ -2625,23 +1886,13 @@ SkTextDecorationStyle toSkTextDecorationStyle(ui.TextDecorationStyle style) { return _skTextDecorationStyles[style.index]; } -@JS() -@staticInterop -class SkTextBaselineEnum {} - -extension SkTextBaselineEnumExtension on SkTextBaselineEnum { +extension type SkTextBaselineEnum(JSObject _) implements JSObject { external SkTextBaseline get Alphabetic; external SkTextBaseline get Ideographic; } -@JS() -@staticInterop -class SkTextBaseline {} - -extension SkTextBaselineExtension on SkTextBaseline { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkTextBaseline(JSObject _) implements JSObject { + external double get value; } final List _skTextBaselines = [ @@ -2653,11 +1904,7 @@ SkTextBaseline toSkTextBaseline(ui.TextBaseline baseline) { return _skTextBaselines[baseline.index]; } -@JS() -@staticInterop -class SkPlaceholderAlignmentEnum {} - -extension SkPlaceholderAlignmentEnumExtension on SkPlaceholderAlignmentEnum { +extension type SkPlaceholderAlignmentEnum(JSObject _) implements JSObject { external SkPlaceholderAlignment get Baseline; external SkPlaceholderAlignment get AboveBaseline; external SkPlaceholderAlignment get BelowBaseline; @@ -2666,14 +1913,8 @@ extension SkPlaceholderAlignmentEnumExtension on SkPlaceholderAlignmentEnum { external SkPlaceholderAlignment get Middle; } -@JS() -@staticInterop -class SkPlaceholderAlignment {} - -extension SkPlaceholderAlignmentExtension on SkPlaceholderAlignment { - @JS('value') - external JSNumber get _value; - double get value => _value.toDartDouble; +extension type SkPlaceholderAlignment(JSObject _) implements JSObject { + external double get value; } final List _skPlaceholderAlignments = [ @@ -2689,14 +1930,9 @@ SkPlaceholderAlignment toSkPlaceholderAlignment(ui.PlaceholderAlignment alignmen return _skPlaceholderAlignments[alignment.index]; } -@JS() -@anonymous -@staticInterop -class SkTextStyleProperties { - external factory SkTextStyleProperties(); -} +extension type SkTextStyleProperties._(JSObject _) implements JSObject { + external SkTextStyleProperties({int dummyArgumentToCreateObjectLiteral}); -extension SkTextStylePropertiesExtension on SkTextStyleProperties { @JS('backgroundColor') external set _backgroundColor(JSFloat32Array? value); set backgroundColor(Float32List? value) => _backgroundColor = value?.toJS; @@ -2709,13 +1945,8 @@ extension SkTextStylePropertiesExtension on SkTextStyleProperties { external set _foregroundColor(JSFloat32Array? value); set foregroundColor(Float32List? value) => _foregroundColor = value?.toJS; - @JS('decoration') - external set _decoration(JSNumber? value); - set decoration(int? value) => _decoration = value?.toJS; - - @JS('decorationThickness') - external set _decorationThickness(JSNumber? value); - set decorationThickness(double? value) => _decorationThickness = value?.toJS; + external set decoration(int? value); + external set decorationThickness(double? value); @JS('decorationColor') external set _decorationColor(JSFloat32Array? value); @@ -2723,30 +1954,12 @@ extension SkTextStylePropertiesExtension on SkTextStyleProperties { external set decorationStyle(SkTextDecorationStyle? value); external set textBaseline(SkTextBaseline? value); - - @JS('fontSize') - external set _fontSize(JSNumber? value); - set fontSize(double? value) => _fontSize = value?.toJS; - - @JS('letterSpacing') - external set _letterSpacing(JSNumber? value); - set letterSpacing(double? value) => _letterSpacing = value?.toJS; - - @JS('wordSpacing') - external set _wordSpacing(JSNumber? value); - set wordSpacing(double? value) => _wordSpacing = value?.toJS; - - @JS('heightMultiplier') - external set _heightMultiplier(JSNumber? value); - set heightMultiplier(double? value) => _heightMultiplier = value?.toJS; - - @JS('halfLeading') - external set _halfLeading(JSBoolean? value); - set halfLeading(bool? value) => _halfLeading = value?.toJS; - - @JS('locale') - external set _locale(JSString? value); - set locale(String? value) => _locale = value?.toJS; + external set fontSize(double? value); + external set letterSpacing(double? value); + external set wordSpacing(double? value); + external set heightMultiplier(double? value); + external set halfLeading(bool? value); + external set locale(String? value); @JS('fontFamilies') external set _fontFamilies(JSAny? value); @@ -2768,65 +1981,32 @@ extension SkTextStylePropertiesExtension on SkTextStyleProperties { _fontVariations = (value as List?)?.toJS; } -@JS() -@anonymous -@staticInterop -class SkStrutStyleProperties { - external factory SkStrutStyleProperties(); -} +extension type SkStrutStyleProperties._(JSObject _) implements JSObject { + external SkStrutStyleProperties({int dummyArgumentToCreateObjectLiteral}); -extension SkStrutStylePropertiesExtension on SkStrutStyleProperties { @JS('fontFamilies') external set _fontFamilies(JSAny? value); set fontFamilies(List? value) => _fontFamilies = value?.toJSAnyShallow; external set fontStyle(SkFontStyle? value); - - @JS('fontSize') - external set _fontSize(JSNumber? value); - set fontSize(double? value) => _fontSize = value?.toJS; - - @JS('heightMultiplier') - external set _heightMultiplier(JSNumber? value); - set heightMultiplier(double? value) => _heightMultiplier = value?.toJS; - - @JS('halfLeading') - external set _halfLeading(JSBoolean? value); - set halfLeading(bool? value) => _halfLeading = value?.toJS; - - @JS('leading') - external set _leading(JSNumber? value); - set leading(double? value) => _leading = value?.toJS; - - @JS('strutEnabled') - external set _strutEnabled(JSBoolean? value); - set strutEnabled(bool? value) => _strutEnabled = value?.toJS; - - @JS('forceStrutHeight') - external set _forceStrutHeight(JSBoolean? value); - set forceStrutHeight(bool? value) => _forceStrutHeight = value?.toJS; + external set fontSize(double? value); + external set heightMultiplier(double? value); + external set halfLeading(bool? value); + external set leading(double? value); + external set strutEnabled(bool? value); + external set forceStrutHeight(bool? value); } -@JS() -@anonymous -@staticInterop -class SkFontStyle { - external factory SkFontStyle(); -} +extension type SkFontStyle._(JSObject _) implements JSObject { + external SkFontStyle({int dummyArgumentToCreateObjectLiteral}); -extension SkFontStyleExtension on SkFontStyle { external set weight(SkFontWeight? value); external set slant(SkFontSlant? value); } -@JS() -@anonymous -@staticInterop -class SkTextShadow { - external factory SkTextShadow(); -} +extension type SkTextShadow._(JSObject _) implements JSObject { + external SkTextShadow({int dummyArgumentToCreateObjectLiteral}); -extension SkTextShadowExtension on SkTextShadow { @JS('color') external set _color(JSFloat32Array? value); set color(Float32List? value) => _color = value?.toJS; @@ -2835,78 +2015,43 @@ extension SkTextShadowExtension on SkTextShadow { external set _offset(JSFloat32Array? value); set offset(Float32List? value) => _offset = value?.toJS; - @JS('blurRadius') - external set _blurRadius(JSNumber? value); - set blurRadius(double? value) => _blurRadius = value?.toJS; + external set blurRadius(double? value); } -@JS() -@anonymous -@staticInterop -class SkFontFeature { - external factory SkFontFeature(); +extension type SkFontFeature._(JSObject _) implements JSObject { + external SkFontFeature({int dummyArgumentToCreateObjectLiteral}); + + external set name(String? value); + external set value(int? v); } -extension SkFontFeatureExtension on SkFontFeature { - @JS('name') - external set _name(JSString? value); - set name(String? value) => _name = value?.toJS; +extension type SkFontVariation._(JSObject _) implements JSObject { + external SkFontVariation({int dummyArgumentToCreateObjectLiteral}); - @JS('value') - external set _value(JSNumber? value); - set value(int? v) => _value = v?.toJS; + external set axis(String? value); + external set value(double? v); } -@JS() -@anonymous -@staticInterop -class SkFontVariation { - external factory SkFontVariation(); -} - -extension SkFontVariationExtension on SkFontVariation { - @JS('axis') - external set _axis(JSString? value); - set axis(String? value) => _axis = value?.toJS; - - @JS('value') - external set _value(JSNumber? value); - set value(double? v) => _value = v?.toJS; -} - -@JS() -@anonymous -@staticInterop -class SkTypeface {} +extension type SkTypeface(JSObject _) implements JSObject {} @JS('window.flutterCanvasKit.Font') -@staticInterop -class SkFont { - external factory SkFont(SkTypeface typeface); -} +extension type SkFont._(JSObject _) implements JSObject { + external SkFont(SkTypeface typeface); -extension SkFontExtension on SkFont { @JS('getGlyphIDs') - external JSUint16Array _getGlyphIDs(JSString text); - Uint16List getGlyphIDs(String text) => _getGlyphIDs(text.toJS).toDart; + external JSUint16Array _getGlyphIDs(String text); + Uint16List getGlyphIDs(String text) => _getGlyphIDs(text).toDart; @JS('getGlyphBounds') - external JSVoid _getGlyphBounds(JSAny glyphs, SkPaint? paint, JSUint8Array? output); + external void _getGlyphBounds(JSAny glyphs, SkPaint? paint, JSUint8Array? output); void getGlyphBounds(List glyphs, SkPaint? paint, Uint8List? output) => _getGlyphBounds(glyphs.toJSAnyShallow, paint, output?.toJS); } -@JS() -@anonymous -@staticInterop -class SkFontMgr {} +extension type SkFontMgr(JSObject _) implements JSObject { + external String? getFamilyName(double fontId); -extension SkFontMgrExtension on SkFontMgr { - @JS('getFamilyName') - external JSString? _getFamilyName(JSNumber fontId); - String? getFamilyName(double fontId) => _getFamilyName(fontId.toJS)?.toDart; - - external JSVoid delete(); + external void delete(); @JS('MakeTypefaceFromData') external SkTypeface? _MakeTypefaceFromData(JSUint8Array font); @@ -2914,87 +2059,34 @@ extension SkFontMgrExtension on SkFontMgr { } @JS('window.flutterCanvasKit.TypefaceFontProvider') -@staticInterop -class TypefaceFontProvider extends SkFontMgr {} - -extension TypefaceFontProviderExtension on TypefaceFontProvider { +extension type TypefaceFontProvider(JSObject _) implements SkFontMgr { @JS('registerFont') - external JSVoid _registerFont(JSUint8Array font, JSString family); - void registerFont(Uint8List font, String family) => _registerFont(font.toJS, family.toJS); + external void _registerFont(JSUint8Array font, String family); + void registerFont(Uint8List font, String family) => _registerFont(font.toJS, family); } -@JS() -@anonymous -@staticInterop -class SkFontCollection {} - -extension SkFontCollectionExtension on SkFontCollection { +extension type SkFontCollection(JSObject _) implements JSObject { external void enableFontFallback(); external void setDefaultFontManager(TypefaceFontProvider? fontManager); external void delete(); } -@JS() -@anonymous -@staticInterop -class SkLineMetrics {} - -extension SkLineMetricsExtension on SkLineMetrics { - @JS('startIndex') - external JSNumber get _startIndex; - double get startIndex => _startIndex.toDartDouble; - - @JS('endIndex') - external JSNumber get _endIndex; - double get endIndex => _endIndex.toDartDouble; - - @JS('endExcludingWhitespaces') - external JSNumber get _endExcludingWhitespaces; - double get endExcludingWhitespaces => _endExcludingWhitespaces.toDartDouble; - - @JS('endIncludingNewline') - external JSNumber get _endIncludingNewline; - double get endIncludingNewline => _endIncludingNewline.toDartDouble; - - @JS('isHardBreak') - external JSBoolean get _isHardBreak; - bool get isHardBreak => _isHardBreak.toDart; - - @JS('ascent') - external JSNumber get _ascent; - double get ascent => _ascent.toDartDouble; - - @JS('descent') - external JSNumber get _descent; - double get descent => _descent.toDartDouble; - - @JS('height') - external JSNumber get _height; - double get height => _height.toDartDouble; - - @JS('width') - external JSNumber get _width; - double get width => _width.toDartDouble; - - @JS('left') - external JSNumber get _left; - double get left => _left.toDartDouble; - - @JS('baseline') - external JSNumber get _baseline; - double get baseline => _baseline.toDartDouble; - - @JS('lineNumber') - external JSNumber get _lineNumber; - double get lineNumber => _lineNumber.toDartDouble; +extension type SkLineMetrics(JSObject _) implements JSObject { + external double get startIndex; + external double get endIndex; + external double get endExcludingWhitespaces; + external double get endIncludingNewline; + external bool get isHardBreak; + external double get ascent; + external double get descent; + external double get height; + external double get width; + external double get left; + external double get baseline; + external double get lineNumber; } -@JS() -@anonymous -@staticInterop -class SkGlyphClusterInfo {} - -extension SkGlyphClusterInfoExtension on SkGlyphClusterInfo { +extension type SkGlyphClusterInfo(JSObject _) implements JSObject { @JS('graphemeLayoutBounds') external JSArray get _bounds; @@ -3020,12 +2112,7 @@ extension SkGlyphClusterInfoExtension on SkGlyphClusterInfo { } } -@JS() -@anonymous -@staticInterop -class SkRectWithDirection {} - -extension SkRectWithDirectionExtension on SkRectWithDirection { +extension type SkRectWithDirection(JSObject _) implements JSObject { @JS('rect') external JSFloat32Array get _rect; Float32List get rect => _rect.toDart; @@ -3037,64 +2124,28 @@ extension SkRectWithDirectionExtension on SkRectWithDirection { external SkTextDirection dir; } -@JS() -@anonymous -@staticInterop -class SkParagraph {} - -extension SkParagraphExtension on SkParagraph { - @JS('getAlphabeticBaseline') - external JSNumber _getAlphabeticBaseline(); - double getAlphabeticBaseline() => _getAlphabeticBaseline().toDartDouble; - - @JS('didExceedMaxLines') - external JSBoolean _didExceedMaxLines(); - bool didExceedMaxLines() => _didExceedMaxLines().toDart; - - @JS('getHeight') - external JSNumber _getHeight(); - double getHeight() => _getHeight().toDartDouble; - - @JS('getIdeographicBaseline') - external JSNumber _getIdeographicBaseline(); - double getIdeographicBaseline() => _getIdeographicBaseline().toDartDouble; +extension type SkParagraph(JSObject _) implements JSObject { + external double getAlphabeticBaseline(); + external bool didExceedMaxLines(); + external double getHeight(); + external double getIdeographicBaseline(); @JS('getLineMetrics') external JSArray _getLineMetrics(); List getLineMetrics() => _getLineMetrics().toDart.cast(); - @JS('getLineMetricsAt') - external SkLineMetrics? _getLineMetricsAt(JSNumber index); - SkLineMetrics? getLineMetricsAt(double index) => _getLineMetricsAt(index.toJS); - - @JS('getNumberOfLines') - external JSNumber _getNumberOfLines(); - double getNumberOfLines() => _getNumberOfLines().toDartDouble; - - @JS('getLineNumberAt') - external JSNumber _getLineNumberAt(JSNumber index); - double getLineNumberAt(double index) => _getLineNumberAt(index.toJS).toDartDouble; - - @JS('getLongestLine') - external JSNumber _getLongestLine(); - double getLongestLine() => _getLongestLine().toDartDouble; - - @JS('getMaxIntrinsicWidth') - external JSNumber _getMaxIntrinsicWidth(); - double getMaxIntrinsicWidth() => _getMaxIntrinsicWidth().toDartDouble; - - @JS('getMinIntrinsicWidth') - external JSNumber _getMinIntrinsicWidth(); - double getMinIntrinsicWidth() => _getMinIntrinsicWidth().toDartDouble; - - @JS('getMaxWidth') - external JSNumber _getMaxWidth(); - double getMaxWidth() => _getMaxWidth().toDartDouble; + external SkLineMetrics? getLineMetricsAt(double index); + external double getNumberOfLines(); + external double getLineNumberAt(double index); + external double getLongestLine(); + external double getMaxIntrinsicWidth(); + external double getMinIntrinsicWidth(); + external double getMaxWidth(); @JS('getRectsForRange') external JSArray _getRectsForRange( - JSNumber start, - JSNumber end, + double start, + double end, SkRectHeightStyle heightStyle, SkRectWidthStyle widthStyle, ); @@ -3103,89 +2154,48 @@ extension SkParagraphExtension on SkParagraph { double end, SkRectHeightStyle heightStyle, SkRectWidthStyle widthStyle, - ) => - _getRectsForRange( - start.toJS, - end.toJS, - heightStyle, - widthStyle, - ).toDart.cast(); + ) => _getRectsForRange(start, end, heightStyle, widthStyle).toDart.cast(); @JS('getRectsForPlaceholders') external JSArray _getRectsForPlaceholders(); List getRectsForPlaceholders() => _getRectsForPlaceholders().toDart.cast(); - @JS('getGlyphPositionAtCoordinate') - external SkTextPosition _getGlyphPositionAtCoordinate(JSNumber x, JSNumber y); - SkTextPosition getGlyphPositionAtCoordinate(double x, double y) => - _getGlyphPositionAtCoordinate(x.toJS, y.toJS); + external SkTextPosition getGlyphPositionAtCoordinate(double x, double y); @JS('getGlyphInfoAt') - external SkGlyphClusterInfo? _getGlyphInfoAt(JSNumber position); - ui.GlyphInfo? getGlyphInfoAt(double position) => _getGlyphInfoAt(position.toJS)?._glyphInfo; + external SkGlyphClusterInfo? _getGlyphInfoAt(double position); + ui.GlyphInfo? getGlyphInfoAt(double position) => _getGlyphInfoAt(position)?._glyphInfo; @JS('getClosestGlyphInfoAtCoordinate') - external SkGlyphClusterInfo? _getClosestGlyphInfoAtCoordinate(JSNumber x, JSNumber y); + external SkGlyphClusterInfo? _getClosestGlyphInfoAtCoordinate(double x, double y); ui.GlyphInfo? getClosestGlyphInfoAt(double x, double y) => - _getClosestGlyphInfoAtCoordinate(x.toJS, y.toJS)?._glyphInfo; + _getClosestGlyphInfoAtCoordinate(x, y)?._glyphInfo; - @JS('getWordBoundary') - external SkTextRange _getWordBoundary(JSNumber position); - SkTextRange getWordBoundary(double position) => _getWordBoundary(position.toJS); - - @JS('layout') - external JSVoid _layout(JSNumber width); - void layout(double width) => _layout(width.toJS); - - external JSVoid delete(); + external SkTextRange getWordBoundary(double position); + external void layout(double width); + external void delete(); } -@JS() -@staticInterop -class SkTextPosition {} - -extension SkTextPositionExtnsion on SkTextPosition { +extension type SkTextPosition(JSObject _) implements JSObject { external SkAffinity get affinity; - - @JS('pos') - external JSNumber get _pos; - double get pos => _pos.toDartDouble; + external double get pos; } -@JS() -@staticInterop -class SkTextRange {} - -extension SkTextRangeExtension on SkTextRange { - @JS('start') - external JSNumber get _start; - double get start => _start.toDartDouble; - - @JS('end') - external JSNumber get _end; - double get end => _end.toDartDouble; +extension type SkTextRange(JSObject _) implements JSObject { + external double get start; + external double get end; } -@JS() -@anonymous -@staticInterop -class SkVertices {} - -extension SkVerticesExtension on SkVertices { - external JSVoid delete(); +extension type SkVertices(JSObject _) implements JSObject { + external void delete(); } -@JS() -@anonymous -@staticInterop -class SkTonalColors { +extension type SkTonalColors._(JSObject _) implements JSObject { factory SkTonalColors({required Float32List ambient, required Float32List spot}) => - SkTonalColors._(ambient: ambient.toJS, spot: spot.toJS); - external factory SkTonalColors._({required JSFloat32Array ambient, required JSFloat32Array spot}); -} + SkTonalColors.make(ambient: ambient.toJS, spot: spot.toJS); + external SkTonalColors.make({required JSFloat32Array ambient, required JSFloat32Array spot}); -extension SkTonalColorsExtension on SkTonalColors { @JS('ambient') external JSFloat32Array get _ambient; Float32List get ambient => _ambient.toDart; @@ -3195,39 +2205,22 @@ extension SkTonalColorsExtension on SkTonalColors { Float32List get spot => _spot.toDart; } -@JS() -@staticInterop -class SkFontMgrNamespace {} - -extension SkFontMgrNamespaceExtension on SkFontMgrNamespace { +extension type SkFontMgrNamespace(JSObject _) implements JSObject { // TODO(yjbanov): can this be made non-null? It returns null in our unit-tests right now. @JS('FromData') external SkFontMgr? _FromData(JSAny fonts); SkFontMgr? FromData(List fonts) => _FromData(fonts.toJSAnyShallow); } -@JS() -@staticInterop -class TypefaceFontProviderNamespace {} - -extension TypefaceFontProviderNamespaceExtension on TypefaceFontProviderNamespace { +extension type TypefaceFontProviderNamespace(JSObject _) implements JSObject { external TypefaceFontProvider Make(); } -@JS() -@staticInterop -class FontCollectionNamespace {} - -extension FontCollectionNamespaceExtension on FontCollectionNamespace { +extension type FontCollectionNamespace(JSObject _) implements JSObject { external SkFontCollection Make(); } -@JS() -@anonymous -@staticInterop -class SkTypefaceFactory {} - -extension SkTypefaceFactoryExtension on SkTypefaceFactory { +extension type SkTypefaceFactory(JSObject _) implements JSObject { @JS('MakeFreeTypeFaceFromData') external SkTypeface? _MakeFreeTypeFaceFromData(JSArrayBuffer fontData); SkTypeface? MakeFreeTypeFaceFromData(ByteBuffer fontData) => @@ -3235,19 +2228,12 @@ extension SkTypefaceFactoryExtension on SkTypefaceFactory { } /// Any Skia object that has a `delete` method. -@JS() -@anonymous -@staticInterop -class SkDeletable {} - -extension SkDeletableExtension on SkDeletable { +extension type SkDeletable(JSObject _) implements JSObject { /// Deletes the C++ side object. - external JSVoid delete(); + external void delete(); /// Returns whether the corresponding C++ object has been deleted. - @JS('isDeleted') - external JSBoolean _isDeleted(); - bool isDeleted() => _isDeleted().toDart; + external bool isDeleted(); /// Returns the JavaScript constructor for this object. /// @@ -3255,151 +2241,74 @@ extension SkDeletableExtension on SkDeletable { external JsConstructor get constructor; } -@JS() -@anonymous -@staticInterop -class JsConstructor {} - -extension JsConstructorExtension on JsConstructor { +extension type JsConstructor(JSObject _) implements JSObject { /// The name of the "constructor", typically the function name called with /// the `new` keyword, or the ES6 class name. /// /// This is useful for debugging. - @JS('name') - external JSString get _name; - String get name => _name.toDart; + external bool get name; } -@JS() -@staticInterop -class SkData {} +extension type SkData(JSObject _) implements JSObject { + external double size(); -extension SkDataExtension on SkData { - @JS('size') - external JSNumber _size(); - double size() => _size().toDartDouble; - - @JS('isEmpty') - external JSBoolean _isEmpty(); - bool isEmpty() => _isEmpty().toDart; + external bool isEmpty(); @JS('bytes') external JSUint8Array _bytes(); Uint8List bytes() => _bytes().toDart; - external JSVoid delete(); + external void delete(); } -@JS() -@anonymous -@staticInterop -class SkImageInfo { - factory SkImageInfo({ +extension type SkImageInfo._(JSObject _) implements JSObject { + external SkImageInfo({ required double width, required double height, required SkColorType colorType, required SkAlphaType alphaType, required ColorSpace colorSpace, - }) => SkImageInfo._( - width: width.toJS, - height: height.toJS, - colorType: colorType, - alphaType: alphaType, - colorSpace: colorSpace, - ); - external factory SkImageInfo._({ - required JSNumber width, - required JSNumber height, - required SkColorType colorType, - required SkAlphaType alphaType, - required ColorSpace colorSpace, }); -} -extension SkImageInfoExtension on SkImageInfo { external SkAlphaType get alphaType; external ColorSpace get colorSpace; external SkColorType get colorType; - @JS('height') - external JSNumber get _height; - double get height => _height.toDartDouble; - - @JS('isEmpty') - external JSBoolean get _isEmpty; - bool get isEmpty => _isEmpty.toDart; - - @JS('isOpaque') - external JSBoolean get _isOpaque; - bool get isOpaque => _isOpaque.toDart; + external double get height; + external double get width; + external bool get isEmpty; + external bool get isOpaque; @JS('bounds') external JSFloat32Array get _bounds; Float32List get bounds => _bounds.toDart; - @JS('width') - external JSNumber get _width; - double get width => _width.toDartDouble; - external SkImageInfo makeAlphaType(SkAlphaType alphaType); external SkImageInfo makeColorSpace(ColorSpace colorSpace); external SkImageInfo makeColorType(SkColorType colorType); - - @JS('makeWH') - external SkImageInfo _makeWH(JSNumber width, JSNumber height); - SkImageInfo makeWH(double width, double height) => _makeWH(width.toJS, height.toJS); + external SkImageInfo makeWH(double width, double height); } -@JS() -@anonymous -@staticInterop -class SkPartialImageInfo { - factory SkPartialImageInfo({ +extension type SkPartialImageInfo._(JSObject _) implements JSObject { + external SkPartialImageInfo({ required double width, required double height, required SkColorType colorType, required SkAlphaType alphaType, required ColorSpace colorSpace, - }) => SkPartialImageInfo._( - width: width.toJS, - height: height.toJS, - colorType: colorType, - alphaType: alphaType, - colorSpace: colorSpace, - ); - external factory SkPartialImageInfo._({ - required JSNumber width, - required JSNumber height, - required SkColorType colorType, - required SkAlphaType alphaType, - required ColorSpace colorSpace, }); -} -extension SkPartialImageInfoExtension on SkPartialImageInfo { external SkAlphaType get alphaType; external ColorSpace get colorSpace; external SkColorType get colorType; - @JS('height') - external JSNumber get _height; - double get height => _height.toDartDouble; + external double get height; - @JS('width') - external JSNumber get _width; - double get width => _width.toDartDouble; + external double get width; } @JS('window.flutterCanvasKit.RuntimeEffect') -@anonymous -@staticInterop -class SkRuntimeEffect {} - -@JS('window.flutterCanvasKit.RuntimeEffect.Make') -external SkRuntimeEffect? _MakeRuntimeEffect(JSString program); -SkRuntimeEffect? MakeRuntimeEffect(String program) => _MakeRuntimeEffect(program.toJS); - -extension SkSkRuntimeEffectExtension on SkRuntimeEffect { +extension type SkRuntimeEffect(JSObject _) implements JSObject { @JS('makeShader') external SkShader? _makeShader(JSAny uniforms); SkShader? makeShader(SkFloat32List uniforms) => _makeShader(uniforms.toJSAnyShallow); @@ -3410,6 +2319,10 @@ extension SkSkRuntimeEffectExtension on SkRuntimeEffect { _makeShaderWithChildren(uniforms.toJSAnyShallow, children.toJSAnyShallow); } +@JS('window.flutterCanvasKit.RuntimeEffect.Make') +external SkRuntimeEffect? _MakeRuntimeEffect(String program); +SkRuntimeEffect? MakeRuntimeEffect(String program) => _MakeRuntimeEffect(program); + const String _kFullCanvasKitJsFileName = 'canvaskit.js'; const String _kChromiumCanvasKitJsFileName = 'chromium/canvaskit.js'; @@ -3479,7 +2392,7 @@ Future _downloadOneOf(Iterable urls) async { } String _resolveUrl(String url) { - return createDomURL(url, domWindow.document.baseUri).toJSString().toDart; + return createDomURL(url, domWindow.document.baseUri).toJSString(); } /// Downloads the CanvasKit JavaScript file at [url]. diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/image.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/image.dart index 57f51c57b6e..761e75cd4ac 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/image.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/image.dart @@ -401,14 +401,14 @@ Future readChunked( int contentLength, ui_web.ImageCodecChunkCallback chunkCallback, ) async { - final JSUint8Array result = createUint8ArrayFromLength(contentLength); + final JSUint8Array result = JSUint8Array.withLength(contentLength); int position = 0; int cumulativeBytesLoaded = 0; - await payload.read((JSUint8Array chunk) { - cumulativeBytesLoaded += chunk.length.toDartInt; + await payload.read((JSUint8Array chunk) { + cumulativeBytesLoaded += chunk.length; chunkCallback(cumulativeBytesLoaded, contentLength); - result.set(chunk, position.toJS); - position += chunk.length.toDartInt; + result.set(chunk, position); + position += chunk.length; }); return result.toDart; } @@ -533,8 +533,8 @@ class CkImage implements ui.Image, StackTraceDebugger { return readPixelsFromDomImageSource( imageBitmap, format, - imageBitmap.width.toDartInt, - imageBitmap.height.toDartInt, + imageBitmap.width, + imageBitmap.height, ); case VideoFrameImageSource(): final VideoFrame videoFrame = (imageSource! as VideoFrameImageSource).videoFrame; @@ -725,10 +725,10 @@ class ImageBitmapImageSource extends ImageSource { } @override - int get height => imageBitmap.height.toDartInt; + int get height => imageBitmap.height; @override - int get width => imageBitmap.width.toDartInt; + int get width => imageBitmap.width; @override DomCanvasImageSource get canvasImageSource => imageBitmap; diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/image_web_codecs.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/image_web_codecs.dart index dadb7958411..7e2d9f4c3f6 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/image_web_codecs.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/image_web_codecs.dart @@ -176,7 +176,7 @@ Future readVideoFramePixelsUnmodified(VideoFrame videoFrame) async { // In dart2wasm, Uint8List is not the same as a JS Uint8Array. So we // explicitly construct the JS object here. - final JSUint8Array destination = createUint8ArrayFromLength(size); + final JSUint8Array destination = JSUint8Array.withLength(size); final JSPromise copyPromise = videoFrame.copyTo(destination); await promiseToFuture(copyPromise); @@ -190,7 +190,7 @@ ByteBuffer readDomImageSourcePixelsUnmodified( int width, int height, ) { - final DomCanvasElement htmlCanvas = createDomCanvasElement(width: width, height: height); + final DomHTMLCanvasElement htmlCanvas = createDomCanvasElement(width: width, height: height); final DomCanvasRenderingContext2D ctx = htmlCanvas.getContext('2d')! as DomCanvasRenderingContext2D; ctx.drawImage(imageSource, 0, 0); @@ -207,7 +207,7 @@ Future encodeDomImageSourceAsPng( int width, int height, ) async { - final DomCanvasElement canvas = createDomCanvasElement(width: width, height: height); + final DomHTMLCanvasElement canvas = createDomCanvasElement(width: width, height: height); final DomCanvasRenderingContext2D ctx = canvas.context2D; ctx.drawImage(imageSource, 0, 0); final String pngBase64 = canvas.toDataURL().substring('data:image/png;base64,'.length); diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/native_memory.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/native_memory.dart index 93104c1f1fe..aed17e5e932 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/native_memory.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/native_memory.dart @@ -21,7 +21,7 @@ import 'package:ui/src/engine.dart'; /// 5. The finalizer function is called with the SkPaint as the sole argument. /// 6. We call `delete` on SkPaint. DomFinalizationRegistry _finalizationRegistry = DomFinalizationRegistry( - ((ExternalDartReference> boxedUniq) => boxedUniq.toDartObject.collect()).toJS, + ((ExternalDartReference> boxedUniq) => boxedUniq.toDartObject.collect()).toJS, ); NativeMemoryFinalizationRegistry nativeMemoryFinalizationRegistry = @@ -30,7 +30,7 @@ NativeMemoryFinalizationRegistry nativeMemoryFinalizationRegistry = /// An indirection to [DomFinalizationRegistry] to enable tests provide a /// mock implementation of a finalization registry. class NativeMemoryFinalizationRegistry { - void register(Object owner, UniqueRef ref) { + void register(Object owner, UniqueRef ref) { if (browserSupportsFinalizationRegistry) { _finalizationRegistry.register(owner.toExternalReference, ref.toExternalReference); } @@ -44,7 +44,7 @@ class NativeMemoryFinalizationRegistry { /// /// To prevent memory leaks, the underlying C++ object is deleted by the GC if /// it wasn't previously disposed of explicitly. -class UniqueRef { +class UniqueRef { UniqueRef(Object owner, T nativeObject, this._debugOwnerLabel) { _nativeObject = nativeObject; if (Instrumentation.enabled) { @@ -134,7 +134,7 @@ abstract class StackTraceDebugger { /// deleted. This is mostly done to prevent memory leaks in production. Well /// behaving framework and app code are expected to rely on [ref] and [unref] /// for timely collection of resources. -class CountedRef { +class CountedRef { /// Creates a counted reference. CountedRef(T nativeObject, R debugReferrer, String debugLabel) { _ref = UniqueRef(this, nativeObject, debugLabel); diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/render_canvas.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/render_canvas.dart index 3c248119361..90171976d0e 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/render_canvas.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/render_canvas.dart @@ -2,8 +2,6 @@ // 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 '../display.dart'; import '../dom.dart'; import '../util.dart'; @@ -47,12 +45,11 @@ class RenderCanvas extends DisplayCanvas { final DomElement hostElement = createDomElement('flt-canvas-container'); /// The underlying `` element used to display the pixels. - final DomCanvasElement canvasElement = createDomCanvasElement(); + final DomHTMLCanvasElement canvasElement = createDomCanvasElement(); int _pixelWidth = 0; int _pixelHeight = 0; - late final DomCanvasRenderingContextBitmapRenderer renderContext = - canvasElement.contextBitmapRenderer; + late final DomImageBitmapRenderingContext renderContext = canvasElement.contextBitmapRenderer; late final DomCanvasRenderingContext2D renderContext2d = canvasElement.context2D; @@ -75,7 +72,7 @@ class RenderCanvas extends DisplayCanvas { /// The canvas will be resized to accomodate the bitmap immediately before /// rendering it. void render(DomImageBitmap bitmap) { - _ensureSize(BitmapSize(bitmap.width.toDartInt, bitmap.height.toDartInt)); + _ensureSize(BitmapSize(bitmap.width, bitmap.height)); renderContext.transferFromImageBitmap(bitmap); } diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/surface.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/surface.dart index a19541cd666..c5748697277 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/surface.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/surface.dart @@ -103,7 +103,7 @@ class Surface extends DisplayCanvas { /// The backing this Surface in the case that OffscreenCanvas isn't /// supported. - DomCanvasElement? _canvasElement; + DomHTMLCanvasElement? _canvasElement; /// Note, if this getter is called, then this Surface is being used as an /// overlay and must be backed by an onscreen element. @@ -153,7 +153,7 @@ class Surface extends DisplayCanvas { if (useOffscreenCanvas) { bitmap = _offscreenCanvas!.transferToImageBitmap(); } else { - bitmapSource = _canvasElement! as JSObject; + bitmapSource = _canvasElement!; bitmap = await createImageBitmap(bitmapSource, ( x: 0, y: _pixelHeight - bitmapSize.height, @@ -291,7 +291,7 @@ class Surface extends DisplayCanvas { return _surface = _createNewSurface(size); } - JSVoid _contextRestoredListener(DomEvent event) { + void _contextRestoredListener(DomEvent event) { assert( _contextLost, 'Received "webglcontextrestored" event but never received ' @@ -304,7 +304,7 @@ class Surface extends DisplayCanvas { event.preventDefault(); } - JSVoid _contextLostListener(DomEvent event) { + void _contextLostListener(DomEvent event) { assert( event.target == _offscreenCanvas || event.target == _canvasElement, 'Received a context lost event for a disposed canvas', @@ -323,9 +323,13 @@ class Surface extends DisplayCanvas { _offscreenCanvas!.removeEventListener( 'webglcontextrestored', _cachedContextRestoredListener, - false, + false.toJS, + ); + _offscreenCanvas!.removeEventListener( + 'webglcontextlost', + _cachedContextLostListener, + false.toJS, ); - _offscreenCanvas!.removeEventListener('webglcontextlost', _cachedContextLostListener, false); _offscreenCanvas = null; _cachedContextRestoredListener = null; _cachedContextLostListener = null; @@ -333,9 +337,13 @@ class Surface extends DisplayCanvas { _canvasElement!.removeEventListener( 'webglcontextrestored', _cachedContextRestoredListener, - false, + false.toJS, + ); + _canvasElement!.removeEventListener( + 'webglcontextlost', + _cachedContextLostListener, + false.toJS, ); - _canvasElement!.removeEventListener('webglcontextlost', _cachedContextLostListener, false); _canvasElement!.remove(); _canvasElement = null; _cachedContextRestoredListener = null; @@ -356,7 +364,7 @@ class Surface extends DisplayCanvas { _offscreenCanvas = offscreenCanvas; _canvasElement = null; } else { - final DomCanvasElement canvas = createDomCanvasElement( + final DomHTMLCanvasElement canvas = createDomCanvasElement( width: _pixelWidth, height: _pixelHeight, ); @@ -379,8 +387,8 @@ class Surface extends DisplayCanvas { // See also: https://www.khronos.org/webgl/wiki/HandlingContextLost _cachedContextRestoredListener = createDomEventListener(_contextRestoredListener); _cachedContextLostListener = createDomEventListener(_contextLostListener); - htmlCanvas.addEventListener('webglcontextlost', _cachedContextLostListener, false); - htmlCanvas.addEventListener('webglcontextrestored', _cachedContextRestoredListener, false); + htmlCanvas.addEventListener('webglcontextlost', _cachedContextLostListener, false.toJS); + htmlCanvas.addEventListener('webglcontextrestored', _cachedContextRestoredListener, false.toJS); _forceNewContext = false; _contextLost = false; @@ -490,11 +498,15 @@ class Surface extends DisplayCanvas { @override void dispose() { - _offscreenCanvas?.removeEventListener('webglcontextlost', _cachedContextLostListener, false); + _offscreenCanvas?.removeEventListener( + 'webglcontextlost', + _cachedContextLostListener, + false.toJS, + ); _offscreenCanvas?.removeEventListener( 'webglcontextrestored', _cachedContextRestoredListener, - false, + false.toJS, ); _cachedContextLostListener = null; _cachedContextRestoredListener = null; diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/configuration.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/configuration.dart index 91cc90d9be6..36696cf89fc 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/configuration.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/configuration.dart @@ -347,67 +347,25 @@ class FlutterConfiguration { external JsFlutterConfiguration? get _jsConfiguration; /// The JS bindings for the object that's set as `window.flutterConfiguration`. -@JS() -@anonymous -@staticInterop -class JsFlutterConfiguration { - external factory JsFlutterConfiguration(); -} - -extension JsFlutterConfigurationExtension on JsFlutterConfiguration { - @JS('assetBase') - external JSString? get _assetBase; - String? get assetBase => _assetBase?.toDart; - - @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('canvasKitForceMultiSurfaceRasterizer') - external JSBoolean? get _canvasKitForceMultiSurfaceRasterizer; - bool? get canvasKitForceMultiSurfaceRasterizer => _canvasKitForceMultiSurfaceRasterizer?.toDart; - - @JS('canvasKitMaximumSurfaces') - external JSNumber? get _canvasKitMaximumSurfaces; - double? get canvasKitMaximumSurfaces => _canvasKitMaximumSurfaces?.toDartDouble; - - @JS('debugShowSemanticsNodes') - external JSBoolean? get _debugShowSemanticsNodes; - bool? get debugShowSemanticsNodes => _debugShowSemanticsNodes?.toDart; +extension type JsFlutterConfiguration._(JSObject _) implements JSObject { + factory JsFlutterConfiguration() => JSObject() as JsFlutterConfiguration; + external String? get assetBase; + external String? get canvasKitBaseUrl; + external String? get canvasKitVariant; + external bool? get canvasKitForceCpuOnly; + external bool? get canvasKitForceMultiSurfaceRasterizer; + external double? get canvasKitMaximumSurfaces; + external bool? get debugShowSemanticsNodes; external DomElement? get hostElement; - - @JS('multiViewEnabled') - external JSBoolean? get _multiViewEnabled; - bool? get multiViewEnabled => _multiViewEnabled?.toDart; - - @JS('nonce') - external JSString? get _nonce; - String? get nonce => _nonce?.toDart; - - @JS('renderer') - external JSString? get _renderer; - String? get renderer => _renderer?.toDart; - - @JS('fontFallbackBaseUrl') - external JSString? get _fontFallbackBaseUrl; - String? get fontFallbackBaseUrl => _fontFallbackBaseUrl?.toDart; - - @JS('forceSingleThreadedSkwasm') - external JSBoolean? get _forceSingleThreadedSkwasm; - bool? get forceSingleThreadedSkwasm => _forceSingleThreadedSkwasm?.toDart; + external bool? get multiViewEnabled; + external String? get nonce; + external String? get renderer; + external String? get fontFallbackBaseUrl; + external bool? get forceSingleThreadedSkwasm; } /// A JavaScript entrypoint that allows developer to set rendering backend /// at runtime before launching the application. @JS('window.flutterWebRenderer') -external JSString? get __requestedRendererType; -String? get _requestedRendererType => __requestedRendererType?.toDart; +external String? get _requestedRendererType; diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/dom.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/dom.dart index dc3ac3a346f..7ed8e21854c 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/dom.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/dom.dart @@ -4,10 +4,10 @@ import 'dart:async'; import 'dart:js_interop'; +import 'dart:js_interop_unsafe'; import 'dart:math' as math; import 'dart:typed_data'; -import 'package:js/js_util.dart' as js_util; import 'package:meta/meta.dart'; import 'browser_detection.dart'; @@ -49,7 +49,7 @@ extension ObjectToJSAnyExtension on Object { @pragma('wasm:prefer-inline') @pragma('dart2js:tryInline') - JSAny get toJSAnyDeep => js_util.jsify(this) as JSAny; + JSAny get toJSAnyDeep => jsify()!; } extension JSAnyToObjectExtension on JSAny { @@ -65,42 +65,24 @@ extension JSAnyToObjectExtension on JSAny { @pragma('wasm:prefer-inline') @pragma('dart2js:tryInline') - Object get toObjectDeep => js_util.dartify(this)!; + Object get toObjectDeep => dartify()!; } @JS('Object') external DomObjectConstructor get objectConstructor; -@JS() -@staticInterop -class DomObjectConstructor {} - -extension DomObjectConstructorExtension on DomObjectConstructor { +extension type DomObjectConstructor._(JSObject _) implements JSObject { external JSObject assign(JSAny? target, JSAny? source1, JSAny? source2); } -@JS() -@staticInterop -class DomWindow extends DomEventTarget {} - -extension DomWindowExtension on DomWindow { +@JS('Window') +extension type DomWindow._(JSObject _) implements DomEventTarget { external DomConsole get console; - - @JS('devicePixelRatio') - external JSNumber get _devicePixelRatio; - double get devicePixelRatio => _devicePixelRatio.toDartDouble; - + external double get devicePixelRatio; external DomDocument get document; external DomHistory get history; - - @JS('innerHeight') - external JSNumber? get _innerHeight; - double? get innerHeight => _innerHeight?.toDartDouble; - - @JS('innerWidth') - external JSNumber? get _innerWidth; - double? get innerWidth => _innerWidth?.toDartDouble; - + external double? get innerHeight; + external double? get innerWidth; external DomLocation get location; external DomNavigator get navigator; external DomVisualViewport? get visualViewport; @@ -118,45 +100,44 @@ extension DomWindowExtension on DomWindow { } @JS('fetch') - external JSPromise _fetch(JSString url, [JSAny headers]); + external JSPromise _fetch(String url, [JSAny headers]); // ignore: non_constant_identifier_names external DomURL get URL; - - @JS('dispatchEvent') - external JSBoolean _dispatchEvent(DomEvent event); - bool dispatchEvent(DomEvent event) => _dispatchEvent(event).toDart; - - @JS('matchMedia') - external DomMediaQueryList _matchMedia(JSString? query); - DomMediaQueryList matchMedia(String? query) => _matchMedia(query?.toJS); + external DomMediaQueryList matchMedia(String? query); @JS('getComputedStyle') - external DomCSSStyleDeclaration _getComputedStyle(DomElement elt, [JSString pseudoElt]); + external DomCSSStyleDeclaration _getComputedStyle(DomElement elt, [String pseudoElt]); DomCSSStyleDeclaration getComputedStyle(DomElement elt, [String? pseudoElt]) { if (pseudoElt == null) { return _getComputedStyle(elt); } else { - return _getComputedStyle(elt, pseudoElt.toJS); + return _getComputedStyle(elt, pseudoElt); } } external DomScreen? get screen; + JSFunction _makeAnimationFrameCallbackZoned(DomRequestAnimationFrameCallback callback) { + final ZoneUnaryCallback zonedCallback = Zone.current + .bindUnaryCallback(callback); + return zonedCallback.toJS; + } + @JS('requestAnimationFrame') - external JSNumber _requestAnimationFrame(JSFunction callback); + external double _requestAnimationFrame(JSFunction callback); double requestAnimationFrame(DomRequestAnimationFrameCallback callback) => - _requestAnimationFrame(callback.toJS).toDartDouble; + _requestAnimationFrame(_makeAnimationFrameCallbackZoned(callback)); @JS('postMessage') - external void _postMessage(JSAny message, JSString targetOrigin, [JSArray messagePorts]); + external void _postMessage(JSAny message, String targetOrigin, [JSArray messagePorts]); void postMessage(Object message, String targetOrigin, [List? messagePorts]) { if (messagePorts == null) { - _postMessage(message.toJSAnyShallow, targetOrigin.toJS); + _postMessage(message.toJSAnyShallow, targetOrigin); } else { _postMessage( message.toJSAnyShallow, - targetOrigin.toJS, + targetOrigin, // Cast is necessary so we can call `.toJS` on the right extension. (messagePorts as List).toJS, ); @@ -170,28 +151,24 @@ extension DomWindowExtension on DomWindow { @JS('createImageBitmap') external JSPromise _createImageBitmap(DomImageData source); Future createImageBitmap(DomImageData source) { - return js_util.promiseToFuture(_createImageBitmap(source)); + return _createImageBitmap(source).toDart.then((JSAny? value) => value! as DomImageBitmap); } } typedef DomRequestAnimationFrameCallback = void Function(JSNumber highResTime); -@JS() -@staticInterop -class DomConsole {} - -extension DomConsoleExtension on DomConsole { +extension type DomConsole._(JSObject _) implements JSObject { @JS('warn') - external void _warn(JSString? arg); - void warn(Object? arg) => _warn(arg.toString().toJS); + external void _warn(String? arg); + void warn(Object? arg) => _warn(arg.toString()); @JS('error') - external void _error(JSString? arg); - void error(Object? arg) => _error(arg.toString().toJS); + external void _error(String? arg); + void error(Object? arg) => _error(arg.toString()); @JS('debug') - external void _debug(JSString? arg); - void debug(Object? arg) => _debug(arg.toString().toJS); + external void _debug(String? arg); + void debug(Object? arg) => _debug(arg.toString()); } @JS('window') @@ -204,58 +181,28 @@ external DomIntl get domIntl; external DomSymbol get domSymbol; @JS('createImageBitmap') -external JSPromise _createImageBitmap( - JSAny source, [ - JSNumber x, - JSNumber y, - JSNumber width, - JSNumber height, -]); +external JSPromise _createImageBitmap(JSAny source, [int x, int y, int width, int height]); Future createImageBitmap( JSAny source, [ ({int x, int y, int width, int height})? bounds, ]) { JSPromise jsPromise; if (bounds != null) { - jsPromise = _createImageBitmap( - source, - bounds.x.toJS, - bounds.y.toJS, - bounds.width.toJS, - bounds.height.toJS, - ); + jsPromise = _createImageBitmap(source, bounds.x, bounds.y, bounds.width, bounds.height); } else { jsPromise = _createImageBitmap(source); } - return js_util.promiseToFuture(jsPromise); + return jsPromise.toDart.then((JSAny? value) => value! as DomImageBitmap); } -@JS() -@staticInterop -class DomNavigator {} - -extension DomNavigatorExtension on DomNavigator { +@JS('Navigator') +extension type DomNavigator._(JSObject _) implements JSObject { external DomClipboard? get clipboard; - - @JS('maxTouchPoints') - external JSNumber? get _maxTouchPoints; - double? get maxTouchPoints => _maxTouchPoints?.toDartDouble; - - @JS('vendor') - external JSString get _vendor; - String get vendor => _vendor.toDart; - - @JS('language') - external JSString get _language; - String get language => _language.toDart; - - @JS('platform') - external JSString? get _platform; - String? get platform => _platform?.toDart; - - @JS('userAgent') - external JSString get _userAgent; - String get userAgent => _userAgent.toDart; + external double? get maxTouchPoints; + external String get vendor; + external String get language; + external String? get platform; + external String get userAgent; @JS('languages') external JSArray? get _languages; @@ -263,194 +210,115 @@ extension DomNavigatorExtension on DomNavigator { _languages?.toDart.map((JSAny? any) => (any! as JSString).toDart).toList(); } -@JS() -@staticInterop -class DomDocument extends DomNode {} - -extension DomDocumentExtension on DomDocument { +@JS('Document') +extension type DomDocument._(JSObject _) implements DomNode { external DomElement? get documentElement; - - @JS('querySelector') - external DomElement? _querySelector(JSString selectors); - DomElement? querySelector(String selectors) => _querySelector(selectors.toJS); + external DomElement? querySelector(String selectors); @JS('querySelectorAll') - external _DomList _querySelectorAll(JSString selectors); + external _DomList _querySelectorAll(String selectors); Iterable querySelectorAll(String selectors) => - createDomListWrapper(_querySelectorAll(selectors.toJS)); + createDomListWrapper(_querySelectorAll(selectors)); @JS('createElement') - external DomElement _createElement(JSString name, [JSAny? options]); + external DomElement _createElement(String name, [JSAny? options]); DomElement createElement(String name, [Object? options]) { if (options == null) { - return _createElement(name.toJS); + return _createElement(name); } else { - return _createElement(name.toJS, options.toJSAnyDeep); + return _createElement(name, options.toJSAnyDeep); } } - @JS('execCommand') - external JSBoolean _execCommand(JSString commandId); - bool execCommand(String commandId) => _execCommand(commandId.toJS).toDart; - + external bool execCommand(String commandId); external DomHTMLScriptElement? get currentScript; - - @JS('createElementNS') - external DomElement _createElementNS(JSString namespaceURI, JSString qualifiedName); - DomElement createElementNS(String namespaceURI, String qualifiedName) => - _createElementNS(namespaceURI.toJS, qualifiedName.toJS); - - @JS('createTextNode') - external DomText _createTextNode(JSString data); - DomText createTextNode(String data) => _createTextNode(data.toJS); - - @JS('createEvent') - external DomEvent _createEvent(JSString eventType); - DomEvent createEvent(String eventType) => _createEvent(eventType.toJS); - + external DomElement createElementNS(String namespaceURI, String qualifiedName); + external DomText createTextNode(String data); + external DomEvent createEvent(String eventType); external DomElement? get activeElement; - - @JS('elementFromPoint') - external DomElement? _elementFromPoint(JSNumber x, JSNumber y); - DomElement? elementFromPoint(int x, int y) => _elementFromPoint(x.toJS, y.toJS); + external DomElement? elementFromPoint(int x, int y); } -@JS() -@staticInterop -class DomHTMLDocument extends DomDocument {} - -extension DomHTMLDocumentExtension on DomHTMLDocument { +@JS('HTMLDocument') +extension type DomHTMLDocument._(JSObject _) implements DomDocument { external DomFontFaceSet? get fonts; external DomHTMLHeadElement? get head; external DomHTMLBodyElement? get body; - - @JS('title') - external set _title(JSString? value); - set title(String? value) => _title = value?.toJS; - - @JS('title') - external JSString? get _title; - String? get title => _title?.toDart; + external String? title; @JS('getElementsByTagName') - external _DomList _getElementsByTagName(JSString tag); + external _DomList _getElementsByTagName(String tag); Iterable getElementsByTagName(String tag) => - createDomListWrapper(_getElementsByTagName(tag.toJS)); + createDomListWrapper(_getElementsByTagName(tag)); - external DomElement? get activeElement; - - @JS('getElementById') - external DomElement? _getElementById(JSString id); - DomElement? getElementById(String id) => _getElementById(id.toJS); - - @JS('visibilityState') - external JSString get _visibilityState; - String get visibilityState => _visibilityState.toDart; - - @JS('hasFocus') - external JSBoolean _hasFocus(); - bool hasFocus() => _hasFocus().toDart; + external DomElement? getElementById(String id); + external String get visibilityState; + external bool hasFocus(); } @JS('document') external DomHTMLDocument get domDocument; -@JS() -@staticInterop -class DomEventTarget {} +/// Creates a [DomEventListener] that runs in the current [Zone]. +// TODO(srujzs): It isn't clear whether we should use this all the time or only +// sometimes. Using this as the wrapped handler in `keyboard_binding.dart` for +// example leads to test failures. +DomEventListener createDomEventListener(DartDomEventListener listener) { + final ZoneUnaryCallback zonedListener = Zone.current + .bindUnaryCallback(listener); + return zonedListener.toJS; +} -extension DomEventTargetExtension on DomEventTarget { - @JS('addEventListener') - external void _addEventListener(JSString type, DomEventListener listener, [JSBoolean useCapture]); - void addEventListener(String type, DomEventListener? listener, [bool? useCapture]) { - if (listener != null) { - if (useCapture == null) { - _addEventListener(type.toJS, listener); - } else { - _addEventListener(type.toJS, listener, useCapture.toJS); - } - } - } +@JS('EventTarget') +extension type DomEventTarget._(JSObject _) implements JSObject { + external void addEventListener(String type, DomEventListener? listener, [JSAny options]); - @JS('addEventListener') - external void _addEventListenerWithOptions( - JSString type, - DomEventListener listener, - JSAny options, - ); - void addEventListenerWithOptions( - String type, - DomEventListener listener, - Map options, - ) => _addEventListenerWithOptions(type.toJS, listener, options.toJSAnyDeep); - - @JS('removeEventListener') - external void _removeEventListener( - JSString type, - DomEventListener listener, [ - JSBoolean useCapture, - ]); - void removeEventListener(String type, DomEventListener? listener, [bool? useCapture]) { - if (listener != null) { - if (useCapture == null) { - _removeEventListener(type.toJS, listener); - } else { - _removeEventListener(type.toJS, listener, useCapture.toJS); - } - } - } + external void removeEventListener(String type, DomEventListener? listener, [JSAny options]); @JS('dispatchEvent') - external JSBoolean _dispatchEvent(DomEvent event); - bool dispatchEvent(DomEvent event) => _dispatchEvent(event).toDart; + external bool _dispatchEvent(DomEvent event); + // We need the non-external member for tear-offs. + bool dispatchEvent(DomEvent event) => _dispatchEvent(event); +} + +extension type DomEventListenerOptions._(JSObject _) implements JSObject { + external DomEventListenerOptions({bool capture, bool passive, bool once}); + + external bool capture; + external bool passive; + external bool once; } typedef DartDomEventListener = void Function(DomEvent event); +typedef DomEventListener = JSFunction; -@JS() -@staticInterop -class DomEventListener {} - -DomEventListener createDomEventListener(DartDomEventListener listener) => - listener.toJS as DomEventListener; - -@JS() -@staticInterop -class DomEvent {} - -extension DomEventExtension on DomEvent { +@JS('Event') +extension type DomEvent._(JSObject _) implements JSObject { external DomEventTarget? get target; external DomEventTarget? get currentTarget; + external double? get timeStamp; + external String get type; - @JS('timeStamp') - external JSNumber? get _timeStamp; - double? get timeStamp => _timeStamp?.toDartDouble; - - @JS('type') - external JSString get _type; - String get type => _type.toDart; - - external JSBoolean? get _cancelable; - bool get cancelable => _cancelable?.toDart ?? true; + @JS('cancelable') + external bool? get _cancelable; + bool get cancelable => _cancelable ?? true; external void preventDefault(); external void stopPropagation(); @JS('initEvent') - external void _initEvent(JSString type, [JSBoolean bubbles, JSBoolean cancelable]); + external void _initEvent(String type, [bool bubbles, bool cancelable]); void initEvent(String type, [bool? bubbles, bool? cancelable]) { if (bubbles == null) { - _initEvent(type.toJS); + _initEvent(type); } else if (cancelable == null) { - _initEvent(type.toJS, bubbles.toJS); + _initEvent(type, bubbles); } else { - _initEvent(type.toJS, bubbles.toJS, cancelable.toJS); + _initEvent(type, bubbles, cancelable); } } - @JS('defaultPrevented') - external JSBoolean get _defaultPrevented; - bool get defaultPrevented => _defaultPrevented.toDart; + external bool get defaultPrevented; } DomEvent createDomEvent(String type, String name) { @@ -460,51 +328,25 @@ DomEvent createDomEvent(String type, String name) { } @JS('ProgressEvent') -@staticInterop -class DomProgressEvent extends DomEvent { - factory DomProgressEvent(String type) => DomProgressEvent._(type.toJS); - external factory DomProgressEvent._(JSString type); +extension type DomProgressEvent._(JSObject _) implements DomEvent { + external double? get loaded; + external double? get total; } -extension DomProgressEventExtension on DomProgressEvent { - @JS('loaded') - external JSNumber? get _loaded; - double? get loaded => _loaded?.toDartDouble; - - @JS('total') - external JSNumber? get _total; - double? get total => _total?.toDartDouble; -} - -@JS() -@staticInterop -class DomNode extends DomEventTarget {} - -extension DomNodeExtension on DomNode { +@JS('Node') +extension type DomNode._(JSObject _) implements DomEventTarget { @JS('baseURI') - external JSString? get _baseUri; - String? get baseUri => _baseUri?.toDart; - + external String? get baseUri; external DomNode? get firstChild; - - @JS('innerText') - external JSString get _innerText; - String get innerText => _innerText.toDart; - - @JS('innerText') - external set _innerText(JSString text); - set innerText(String text) => _innerText = text.toJS; - + external String innerText; external DomNode? get lastChild; external DomNode appendChild(DomNode node); - @JS('parentElement') external DomElement? get parentElement; DomElement? get parent => parentElement; @JS('textContent') - external JSString? get _textContent; - String? get text => _textContent?.toDart; + external String? text; external DomNode? get parentNode; external DomNode? get nextSibling; @@ -517,23 +359,9 @@ extension DomNodeExtension on DomNode { } external DomNode removeChild(DomNode child); - - @JS('isConnected') - external JSBoolean? get _isConnected; - bool? get isConnected => _isConnected?.toDart; - - @JS('textContent') - external set _textContent(JSString? value); - set text(String? value) => _textContent = value?.toJS; - - @JS('cloneNode') - external DomNode _cloneNode(JSBoolean? deep); - DomNode cloneNode(bool? deep) => _cloneNode(deep?.toJS); - - @JS('contains') - external JSBoolean _contains(DomNode? other); - bool contains(DomNode? other) => _contains(other).toDart; - + external bool? get isConnected; + external DomNode cloneNode(bool? deep); + external bool contains(DomNode? other); external void append(DomNode node); @JS('childNodes') @@ -548,108 +376,48 @@ extension DomNodeExtension on DomNode { } } -@JS() -@staticInterop -class DomElement extends DomNode {} - -DomElement createDomElement(String tag) => domDocument.createElement(tag); - -extension DomElementExtension on DomElement { +@JS('Element') +extension type DomElement._(JSObject _) implements DomNode { @JS('children') external _DomList get _children; Iterable get children => createDomListWrapper(_children); external DomElement? get firstElementChild; external DomElement? get lastElementChild; - external DomElement? get nextElementSibling; - - @JS('clientHeight') - external JSNumber get _clientHeight; - double get clientHeight => _clientHeight.toDartDouble; - - @JS('clientWidth') - external JSNumber get _clientWidth; - double get clientWidth => _clientWidth.toDartDouble; - - @JS('offsetHeight') - external JSNumber get _offsetHeight; - double get offsetHeight => _offsetHeight.toDartDouble; - - @JS('offsetWidth') - external JSNumber get _offsetWidth; - double get offsetWidth => _offsetWidth.toDartDouble; - - @JS('id') - external JSString get _id; - String get id => _id.toDart; - - @JS('id') - external set _id(JSString id); - set id(String id) => _id = id.toJS; - - @JS('innerHTML') - external set _innerHTML(JSString? html); - set innerHTML(String? html) => _innerHTML = html?.toJS; - - @JS('outerHTML') - external JSString? get _outerHTML; - String? get outerHTML => _outerHTML?.toDart; - - @JS('spellcheck') - external set _spellcheck(JSBoolean? value); - set spellcheck(bool? value) => _spellcheck = value?.toJS; - - @JS('tagName') - external JSString get _tagName; - String get tagName => _tagName.toDart; - + external double get clientHeight; + external double get clientWidth; + external double get offsetHeight; + external double get offsetWidth; + external String id; + external set innerHTML(String? html); + external String? get outerHTML; + external set spellcheck(bool? value); + external String get tagName; external DomCSSStyleDeclaration get style; - external void append(DomNode node); - - @JS('getAttribute') - external JSString? _getAttribute(JSString attributeName); - String? getAttribute(String attributeName) => _getAttribute(attributeName.toJS)?.toDart; - + external String? getAttribute(String attributeName); external DomRect getBoundingClientRect(); external void prepend(DomNode node); - - @JS('querySelector') - external DomElement? _querySelector(JSString selectors); - DomElement? querySelector(String selectors) => _querySelector(selectors.toJS); - - @JS('closest') - external DomElement? _closest(JSString selectors); - DomElement? closest(String selectors) => _closest(selectors.toJS); - - @JS('matches') - external JSBoolean _matches(JSString selectors); - bool matches(String selectors) => _matches(selectors.toJS).toDart; + external DomElement? querySelector(String selectors); + external DomElement? closest(String selectors); + external bool matches(String selectors); @JS('querySelectorAll') - external _DomList _querySelectorAll(JSString selectors); + external _DomList _querySelectorAll(String selectors); Iterable querySelectorAll(String selectors) => - createDomListWrapper(_querySelectorAll(selectors.toJS)); + createDomListWrapper(_querySelectorAll(selectors)); + // TODO(srujzs): Adding @redeclare here is leading to some build failures. + // ignore: annotate_redeclares external void remove(); @JS('setAttribute') - external void _setAttribute(JSString name, JSAny value); - void setAttribute(String name, Object value) => _setAttribute(name.toJS, value.toJSAnyDeep); + external void _setAttribute(String name, JSAny value); + void setAttribute(String name, Object value) => _setAttribute(name, value.toJSAnyDeep); void appendText(String text) => append(createDomText(text)); - - @JS('removeAttribute') - external void _removeAttribute(JSString name); - void removeAttribute(String name) => _removeAttribute(name.toJS); - - @JS('tabIndex') - external set _tabIndex(JSNumber? value); - set tabIndex(double? value) => _tabIndex = value?.toJS; - - @JS('tabIndex') - external JSNumber? get _tabIndex; - double? get tabIndex => _tabIndex?.toDartDouble; + external void removeAttribute(String name); + external double? tabIndex; /// Consider not exposing this method publicly. It defaults `preventScroll` to /// false, which is almost always wrong in Flutter. If you need to expose a @@ -673,80 +441,46 @@ extension DomElementExtension on DomElement { _focus(_preventScrollOptions); } - @JS('scrollTop') - external JSNumber get _scrollTop; - double get scrollTop => _scrollTop.toDartDouble; - - @JS('scrollTop') - external set _scrollTop(JSNumber value); - set scrollTop(double value) => _scrollTop = value.toJS; - - @JS('scrollLeft') - external JSNumber get _scrollLeft; - double get scrollLeft => _scrollLeft.toDartDouble; - - @JS('scrollLeft') - external set _scrollLeft(JSNumber value); - set scrollLeft(double value) => _scrollLeft = value.toJS; - + external double scrollTop; + external double scrollLeft; external DomTokenList get classList; - - @JS('className') - external set _className(JSString value); - set className(String value) => _className = value.toJS; - - @JS('className') - external JSString get _className; - String get className => _className.toDart; + external String className; external void blur(); @JS('getElementsByTagName') - external _DomList _getElementsByTagName(JSString tag); + external _DomList _getElementsByTagName(String tag); Iterable getElementsByTagName(String tag) => - createDomListWrapper(_getElementsByTagName(tag.toJS)); + createDomListWrapper(_getElementsByTagName(tag)); @JS('getElementsByClassName') - external _DomList _getElementsByClassName(JSString className); + external _DomList _getElementsByClassName(String className); Iterable getElementsByClassName(String className) => - createDomListWrapper(_getElementsByClassName(className.toJS)); + createDomListWrapper(_getElementsByClassName(className)); external void click(); - - @JS('hasAttribute') - external JSBoolean _hasAttribute(JSString name); - bool hasAttribute(String name) => _hasAttribute(name.toJS).toDart; - - @JS('childNodes') - external _DomList get _childNodes; - Iterable get childNodes => createDomListWrapper(_childNodes); + external bool hasAttribute(String name); @JS('attachShadow') external DomShadowRoot _attachShadow(JSAny initDict); DomShadowRoot attachShadow(Map initDict) => _attachShadow(initDict.toJSAnyDeep); external DomShadowRoot? get shadowRoot; - void clearChildren() { - while (firstChild != null) { - removeChild(firstChild!); - } - } external void setPointerCapture(num? pointerId); } -extension type DomCSS(JSObject _) implements JSObject { - external bool supports(String proeprty, String value); +DomElement createDomElement(String tag) => domDocument.createElement(tag); + +extension type DomCSS._(JSObject _) implements JSObject { + external bool supports(String property, String value); } @JS('CSS') external DomCSS get domCSS; -@JS() -@staticInterop -class DomCSSStyleDeclaration {} - -extension DomCSSStyleDeclarationExtension on DomCSSStyleDeclaration { +@JS('CSSStyleDeclaration') +extension type DomCSSStyleDeclaration._(JSObject _) implements JSObject { set width(String value) => setProperty('width', value); set height(String value) => setProperty('height', value); set position(String value) => setProperty('position', value); @@ -871,148 +605,66 @@ extension DomCSSStyleDeclarationExtension on DomCSSStyleDeclaration { String get font => getPropertyValue('font'); String get cursor => getPropertyValue('cursor'); - @JS('getPropertyValue') - external JSString _getPropertyValue(JSString property); - String getPropertyValue(String property) => _getPropertyValue(property.toJS).toDart; + external String getPropertyValue(String property); @JS('setProperty') - external void _setProperty(JSString propertyName, JSString value, JSString priority); + external void _setProperty(String propertyName, String value, String priority); void setProperty(String propertyName, String value, [String? priority]) { priority ??= ''; - _setProperty(propertyName.toJS, value.toJS, priority.toJS); + _setProperty(propertyName, value, priority); } - @JS('removeProperty') - external JSString _removeProperty(JSString property); - String removeProperty(String property) => _removeProperty(property.toJS).toDart; + external String removeProperty(String property); } -@JS() -@staticInterop -class DomHTMLElement extends DomElement {} - -extension DomHTMLElementExtension on DomHTMLElement { - @JS('offsetWidth') - external JSNumber get _offsetWidth; - double get offsetWidth => _offsetWidth.toDartDouble; - - @JS('offsetLeft') - external JSNumber get _offsetLeft; - double get offsetLeft => _offsetLeft.toDartDouble; - - @JS('offsetTop') - external JSNumber get _offsetTop; - double get offsetTop => _offsetTop.toDartDouble; - +@JS('HTMLElement') +extension type DomHTMLElement._(JSObject _) implements DomElement { + external double get offsetLeft; + external double get offsetTop; external DomHTMLElement? get offsetParent; } -@JS() -@staticInterop -class DomHTMLMetaElement extends DomHTMLElement {} - -extension DomHTMLMetaElementExtension on DomHTMLMetaElement { - @JS('name') - external JSString get _name; - String get name => _name.toDart; - - @JS('name') - external set _name(JSString value); - set name(String value) => _name = value.toJS; - - @JS('content') - external JSString get _content; - String get content => _content.toDart; - - @JS('content') - external set _content(JSString value); - set content(String value) => _content = value.toJS; +@JS('HTMLMetaElement') +extension type DomHTMLMetaElement._(JSObject _) implements DomHTMLElement { + external String name; + external String content; } DomHTMLMetaElement createDomHTMLMetaElement() => domDocument.createElement('meta') as DomHTMLMetaElement; -@JS() -@staticInterop -class DomHTMLHeadElement extends DomHTMLElement {} +@JS('HTMLHeadElement') +extension type DomHTMLHeadElement._(JSObject _) implements DomHTMLElement {} -@JS() -@staticInterop -class DomHTMLBodyElement extends DomHTMLElement {} +@JS('HTMLBodyElement') +extension type DomHTMLBodyElement._(JSObject _) implements DomHTMLElement {} -@JS() -@staticInterop -class DomHTMLImageElement extends DomHTMLElement implements DomCanvasImageSource {} +@JS('HTMLImageElement') +extension type DomHTMLImageElement._(JSObject _) implements DomHTMLElement, DomCanvasImageSource { + external String? alt; + external String? src; + external double get naturalWidth; + external double get naturalHeight; + external set width(double? value); + external set height(double? value); + external String? crossOrigin; + external String? decoding; + + @JS('decode') + external JSPromise _decode(); + Future decode() => _decode().toDart; +} DomHTMLImageElement createDomHTMLImageElement() => domDocument.createElement('img') as DomHTMLImageElement; -extension DomHTMLImageElementExtension on DomHTMLImageElement { - @JS('alt') - external JSString? get _alt; - String? get alt => _alt?.toDart; - - @JS('alt') - external set _alt(JSString? value); - set alt(String? value) => _alt = value?.toJS; - - @JS('src') - external JSString? get _src; - String? get src => _src?.toDart; - - @JS('src') - external set _src(JSString? value); - set src(String? value) => _src = value?.toJS; - - @JS('naturalWidth') - external JSNumber get _naturalWidth; - double get naturalWidth => _naturalWidth.toDartDouble; - - @JS('naturalHeight') - external JSNumber get _naturalHeight; - double get naturalHeight => _naturalHeight.toDartDouble; - - @JS('width') - external set _width(JSNumber? value); - set width(double? value) => _width = value?.toJS; - - @JS('height') - external set _height(JSNumber? value); - set height(double? value) => _height = value?.toJS; - - @JS('crossOrigin') - external JSString? get _crossOrigin; - String? get crossOrigin => _crossOrigin?.toDart; - - @JS('crossOrigin') - external set _crossOrigin(JSString? value); - set crossOrigin(String? value) => _crossOrigin = value?.toJS; - - @JS('decoding') - external JSString? get _decoding; - String? get decoding => _decoding?.toDart; - - @JS('decoding') - external set _decoding(JSString? value); - set decoding(String? value) => _decoding = value?.toJS; - - @JS('decode') - external JSPromise _decode(); - Future decode() => js_util.promiseToFuture(_decode()); -} - -@JS() -@staticInterop -class DomHTMLScriptElement extends DomHTMLElement {} - -extension DomHTMLScriptElementExtension on DomHTMLScriptElement { +@JS('HTMLScriptElement') +extension type DomHTMLScriptElement._(JSObject _) implements DomHTMLElement { @JS('src') external set _src(JSAny value); set src(Object /* String|TrustedScriptURL */ value) => _src = value.toJSAnyShallow; - @JS('nonce') - external set _nonce(JSString? value); - set nonce(String? value) => _nonce = value?.toJS; + external set nonce(String? value); } DomHTMLScriptElement createDomHTMLScriptElement(String? nonce) { @@ -1023,51 +675,34 @@ DomHTMLScriptElement createDomHTMLScriptElement(String? nonce) { return script; } -@JS() -@staticInterop -class DomHTMLDivElement extends DomHTMLElement {} +@JS('HTMLDivElement') +extension type DomHTMLDivElement._(JSObject _) implements DomHTMLElement {} DomHTMLDivElement createDomHTMLDivElement() => domDocument.createElement('div') as DomHTMLDivElement; -@JS() -@staticInterop -class DomHTMLSpanElement extends DomHTMLElement {} +@JS('HTMLSpanElement') +extension type DomHTMLSpanElement._(JSObject _) implements DomHTMLElement {} DomHTMLSpanElement createDomHTMLSpanElement() => domDocument.createElement('span') as DomHTMLSpanElement; -@JS() -@staticInterop -class DomHTMLButtonElement extends DomHTMLElement {} +@JS('HTMLButtonElement') +extension type DomHTMLButtonElement._(JSObject _) implements DomHTMLElement {} DomHTMLButtonElement createDomHTMLButtonElement() => domDocument.createElement('button') as DomHTMLButtonElement; -@JS() -@staticInterop -class DomHTMLParagraphElement extends DomHTMLElement {} +@JS('HTMLParagraphElement') +extension type DomHTMLParagraphElement._(JSObject _) implements DomHTMLElement {} DomHTMLParagraphElement createDomHTMLParagraphElement() => domDocument.createElement('p') as DomHTMLParagraphElement; -@JS() -@staticInterop -class DomHTMLStyleElement extends DomHTMLElement {} - -extension DomHTMLStyleElementExtension on DomHTMLStyleElement { - @JS('type') - external set _type(JSString? value); - set type(String? value) => _type = value?.toJS; - - @JS('nonce') - external set _nonce(JSString? value); - set nonce(String? value) => _nonce = value?.toJS; - - @JS('nonce') - external JSString? get _nonce; - String? get nonce => _nonce?.toDart; - +@JS('HTMLStyleElement') +extension type DomHTMLStyleElement._(JSObject _) implements DomHTMLElement { + external set type(String? value); + external String? nonce; external DomStyleSheet? get sheet; } @@ -1079,93 +714,35 @@ DomHTMLStyleElement createDomHTMLStyleElement(String? nonce) { return style; } -@JS() -@staticInterop -class DomPerformance extends DomEventTarget {} - -extension DomPerformanceExtension on DomPerformance { - @JS('mark') - external DomPerformanceEntry? _mark(JSString markName); - DomPerformanceEntry? mark(String markName) => _mark(markName.toJS); - - @JS('measure') - external DomPerformanceMeasure? _measure( - JSString measureName, - JSString? startMark, - JSString? endMark, - ); - DomPerformanceMeasure? measure(String measureName, String? startMark, String? endMark) => - _measure(measureName.toJS, startMark?.toJS, endMark?.toJS); - - @JS('now') - external JSNumber _now(); - double now() => _now().toDartDouble; +@JS('Performance') +extension type DomPerformance._(JSObject _) implements DomEventTarget { + external DomPerformanceEntry? mark(String markName); + external DomPerformanceMeasure? measure(String measureName, String? startMark, String? endMark); + external double now(); } -@JS() -@staticInterop -class DomPerformanceEntry {} +@JS('PerformanceEntry') +extension type DomPerformanceEntry._(JSObject _) implements JSObject {} -@JS() -@staticInterop -class DomPerformanceMeasure extends DomPerformanceEntry {} +@JS('PerformanceMeasure') +extension type DomPerformanceMeasure._(JSObject _) implements DomPerformanceEntry {} -@JS() -@staticInterop -class DomCanvasElement extends DomHTMLElement {} - -@visibleForTesting -int debugCanvasCount = 0; - -@visibleForTesting -void debugResetCanvasCount() { - debugCanvasCount = 0; -} - -DomCanvasElement createDomCanvasElement({int? width, int? height}) { - debugCanvasCount++; - final DomCanvasElement canvas = domWindow.document.createElement('canvas') as DomCanvasElement; - if (width != null) { - canvas.width = width.toDouble(); - } - if (height != null) { - canvas.height = height.toDouble(); - } - return canvas; -} - -extension DomCanvasElementExtension on DomCanvasElement { - @JS('width') - external JSNumber? get _width; - double? get width => _width?.toDartDouble; - - @JS('width') - external set _width(JSNumber? value); - set width(double? value) => _width = value?.toJS; - - @JS('height') - external JSNumber? get _height; - double? get height => _height?.toDartDouble; - - @JS('height') - external set _height(JSNumber? value); - set height(double? value) => _height = value?.toJS; - - @JS('isConnected') - external JSBoolean? get _isConnected; - bool? get isConnected => _isConnected?.toDart; +@JS('HTMLCanvasElement') +extension type DomHTMLCanvasElement._(JSObject _) implements DomHTMLElement { + external double? width; + external double? height; @JS('toDataURL') external JSString _toDataURL(JSString type); String toDataURL([String type = 'image/png']) => _toDataURL(type.toJS).toDart; @JS('getContext') - external JSAny? _getContext(JSString contextType, [JSAny attributes]); + external JSAny? _getContext(String contextType, [JSAny attributes]); Object? getContext(String contextType, [Map? attributes]) { if (attributes == null) { - return _getContext(contextType.toJS); + return _getContext(contextType); } else { - return _getContext(contextType.toJS, attributes.toJSAnyDeep); + return _getContext(contextType, attributes.toJSAnyDeep); } } @@ -1178,38 +755,46 @@ extension DomCanvasElementExtension on DomCanvasElement { return getContext('webgl2')! as WebGLContext; } - DomCanvasRenderingContextBitmapRenderer get contextBitmapRenderer => - getContext('bitmaprenderer')! as DomCanvasRenderingContextBitmapRenderer; + DomImageBitmapRenderingContext get contextBitmapRenderer => + getContext('bitmaprenderer')! as DomImageBitmapRenderingContext; } -@JS() -@staticInterop -class WebGLContext {} +@visibleForTesting +int debugCanvasCount = 0; -extension WebGLContextExtension on WebGLContext { - @JS('getParameter') - external JSNumber _getParameter(JSNumber value); - int getParameter(int value) => _getParameter(value.toJS).toDartDouble.toInt(); +@visibleForTesting +void debugResetCanvasCount() { + debugCanvasCount = 0; +} + +DomHTMLCanvasElement createDomCanvasElement({int? width, int? height}) { + debugCanvasCount++; + final DomHTMLCanvasElement canvas = + domWindow.document.createElement('canvas') as DomHTMLCanvasElement; + if (width != null) { + canvas.width = width.toDouble(); + } + if (height != null) { + canvas.height = height.toDouble(); + } + return canvas; +} + +extension type WebGLContext._(JSObject _) implements JSObject { + external int getParameter(int value); @JS('SAMPLES') - external JSNumber get _samples; - int get samples => _samples.toDartDouble.toInt(); + external int get samples; @JS('STENCIL_BITS') - external JSNumber get _stencilBits; - int get stencilBits => _stencilBits.toDartDouble.toInt(); + external int get stencilBits; } -@JS() -@staticInterop -abstract class DomCanvasImageSource {} +extension type DomCanvasImageSource._(JSObject _) implements JSObject {} -@JS() -@staticInterop -class DomCanvasRenderingContext2D {} - -extension DomCanvasRenderingContext2DExtension on DomCanvasRenderingContext2D { - external DomCanvasElement? get canvas; +@JS('CanvasRenderingContext2D') +extension type DomCanvasRenderingContext2D._(JSObject _) implements JSObject { + external DomHTMLCanvasElement? get canvas; @JS('fillStyle') external JSAny? get _fillStyle; @@ -1219,25 +804,9 @@ extension DomCanvasRenderingContext2DExtension on DomCanvasRenderingContext2D { external set _fillStyle(JSAny? style); set fillStyle(Object? style) => _fillStyle = style?.toJSAnyShallow; - @JS('font') - external JSString get _font; - String get font => _font.toDart; - - @JS('font') - external set _font(JSString value); - set font(String value) => _font = value.toJS; - - @JS('direction') - external JSString get _direction; - String get direction => _direction.toDart; - - @JS('direction') - external set _direction(JSString value); - set direction(String value) => _direction = value.toJS; - - @JS('lineWidth') - external set _lineWidth(JSNumber? value); - set lineWidth(num? value) => _lineWidth = value?.toJS; + external String font; + external String direction; + external set lineWidth(num? value); @JS('strokeStyle') external set _strokeStyle(JSAny? value); @@ -1249,45 +818,26 @@ extension DomCanvasRenderingContext2DExtension on DomCanvasRenderingContext2D { external void beginPath(); external void closePath(); - - @JS('createLinearGradient') - external DomCanvasGradient _createLinearGradient( - JSNumber x0, - JSNumber y0, - JSNumber x1, - JSNumber y1, - ); - DomCanvasGradient createLinearGradient(num x0, num y0, num x1, num y1) => - _createLinearGradient(x0.toJS, y0.toJS, x1.toJS, y1.toJS); + external DomCanvasGradient createLinearGradient(num x0, num y0, num x1, num y1); @JS('createPattern') - external DomCanvasPattern? _createPattern(JSAny image, JSString reptitionType); + external DomCanvasPattern? _createPattern(JSAny image, String reptitionType); DomCanvasPattern? createPattern(Object image, String reptitionType) => - _createPattern(image.toJSAnyShallow, reptitionType.toJS); + _createPattern(image.toJSAnyShallow, reptitionType); - @JS('createRadialGradient') - external DomCanvasGradient _createRadialGradient( - JSNumber x0, - JSNumber y0, - JSNumber r0, - JSNumber x1, - JSNumber y1, - JSNumber r1, - ); - DomCanvasGradient createRadialGradient(num x0, num y0, num r0, num x1, num y1, num r1) => - _createRadialGradient(x0.toJS, y0.toJS, r0.toJS, x1.toJS, y1.toJS, r1.toJS); + external DomCanvasGradient createRadialGradient(num x0, num y0, num r0, num x1, num y1, num r1); @JS('drawImage') external void _drawImage( DomCanvasImageSource source, - JSNumber sxOrDx, - JSNumber syOrDy, [ - JSNumber sWidth, - JSNumber sHeight, - JSNumber dx, - JSNumber dy, - JSNumber dWidth, - JSNumber dHeight, + num sxOrDx, + num syOrDy, [ + num sWidth, + num sHeight, + num dx, + num dy, + num dWidth, + num dHeight, ]); void drawImage( DomCanvasImageSource source, @@ -1302,21 +852,21 @@ extension DomCanvasRenderingContext2DExtension on DomCanvasRenderingContext2D { ]) { if (srcWidth == null) { // In this case the numbers provided are the destination x and y offset. - return _drawImage(source, srcxOrDstX.toJS, srcyOrDstY.toJS); + return _drawImage(source, srcxOrDstX, srcyOrDstY); } else { assert( srcHeight != null && dstX != null && dstY != null && dstWidth != null && dstHeight != null, ); return _drawImage( source, - srcxOrDstX.toJS, - srcyOrDstY.toJS, - srcWidth.toJS, - srcHeight!.toJS, - dstX!.toJS, - dstY!.toJS, - dstWidth!.toJS, - dstHeight!.toJS, + srcxOrDstX, + srcyOrDstY, + srcWidth, + srcHeight!, + dstX!, + dstY!, + dstWidth!, + dstHeight!, ); } } @@ -1331,64 +881,29 @@ extension DomCanvasRenderingContext2DExtension on DomCanvasRenderingContext2D { } } - @JS('fillRect') - external void _fillRect(JSNumber x, JSNumber y, JSNumber width, JSNumber height); - void fillRect(num x, num y, num width, num height) => - _fillRect(x.toJS, y.toJS, width.toJS, height.toJS); + external void fillRect(num x, num y, num width, num height); @JS('fillText') - external void _fillText(JSString text, JSNumber x, JSNumber y, [JSNumber maxWidth]); + external void _fillText(String text, num x, num y, [num maxWidth]); void fillText(String text, num x, num y, [num? maxWidth]) { if (maxWidth == null) { - _fillText(text.toJS, x.toJS, y.toJS); + _fillText(text, x, y); } else { - _fillText(text.toJS, x.toJS, y.toJS, maxWidth.toJS); + _fillText(text, x, y, maxWidth); } } - @JS('getImageData') - external DomImageData _getImageData(JSNumber x, JSNumber y, JSNumber sw, JSNumber sh); - DomImageData getImageData(int x, int y, int sw, int sh) => - _getImageData(x.toJS, y.toJS, sw.toJS, sh.toJS); - - @JS('lineTo') - external void _lineTo(JSNumber x, JSNumber y); - void lineTo(num x, num y) => _lineTo(x.toJS, y.toJS); - - @JS('measureText') - external DomTextMetrics _measureText(JSString text); - DomTextMetrics measureText(String text) => _measureText(text.toJS); - - @JS('moveTo') - external void _moveTo(JSNumber x, JSNumber y); - void moveTo(num x, num y) => _moveTo(x.toJS, y.toJS); - + external DomImageData getImageData(int x, int y, int sw, int sh); + external void lineTo(num x, num y); + external DomTextMetrics measureText(String text); + external void moveTo(num x, num y); external void save(); external void stroke(); - - @JS('rect') - external void _rect(JSNumber x, JSNumber y, JSNumber width, JSNumber height); - void rect(num x, num y, num width, num height) => _rect(x.toJS, y.toJS, width.toJS, height.toJS); - + external void rect(num x, num y, num width, num height); external void resetTransform(); external void restore(); - - @JS('setTransform') - external void _setTransform( - JSNumber a, - JSNumber b, - JSNumber c, - JSNumber d, - JSNumber e, - JSNumber f, - ); - void setTransform(num a, num b, num c, num d, num e, num f) => - _setTransform(a.toJS, b.toJS, c.toJS, d.toJS, e.toJS, f.toJS); - - @JS('transform') - external void _transform(JSNumber a, JSNumber b, JSNumber c, JSNumber d, JSNumber e, JSNumber f); - void transform(num a, num b, num c, num d, num e, num f) => - _transform(a.toJS, b.toJS, c.toJS, d.toJS, e.toJS, f.toJS); + external void setTransform(num a, num b, num c, num d, num e, num f); + external void transform(num a, num b, num c, num d, num e, num f); @JS('clip') external void _clip([JSAny pathOrWinding]); @@ -1400,96 +915,27 @@ extension DomCanvasRenderingContext2DExtension on DomCanvasRenderingContext2D { } } - @JS('scale') - external void _scale(JSNumber x, JSNumber y); - void scale(num x, num y) => _scale(x.toJS, y.toJS); - - @JS('clearRect') - external void _clearRect(JSNumber x, JSNumber y, JSNumber width, JSNumber height); - void clearRect(num x, num y, num width, num height) => - _clearRect(x.toJS, y.toJS, width.toJS, height.toJS); - - @JS('translate') - external void _translate(JSNumber x, JSNumber y); - void translate(num x, num y) => _translate(x.toJS, y.toJS); - - @JS('rotate') - external void _rotate(JSNumber angle); - void rotate(num angle) => _rotate(angle.toJS); - - @JS('bezierCurveTo') - external void _bezierCurveTo( - JSNumber cp1x, - JSNumber cp1y, - JSNumber cp2x, - JSNumber cp2y, - JSNumber x, - JSNumber y, - ); - void bezierCurveTo(num cp1x, num cp1y, num cp2x, num cp2y, num x, num y) => - _bezierCurveTo(cp1x.toJS, cp1y.toJS, cp2x.toJS, cp2y.toJS, x.toJS, y.toJS); - - @JS('quadraticCurveTo') - external void _quadraticCurveTo(JSNumber cpx, JSNumber cpy, JSNumber x, JSNumber y); - void quadraticCurveTo(num cpx, num cpy, num x, num y) => - _quadraticCurveTo(cpx.toJS, cpy.toJS, x.toJS, y.toJS); - - @JS('globalCompositeOperation') - external set _globalCompositeOperation(JSString value); - set globalCompositeOperation(String value) => _globalCompositeOperation = value.toJS; - - @JS('lineCap') - external set _lineCap(JSString value); - set lineCap(String value) => _lineCap = value.toJS; - - @JS('lineJoin') - external set _lineJoin(JSString value); - set lineJoin(String value) => _lineJoin = value.toJS; - - @JS('shadowBlur') - external set _shadowBlur(JSNumber value); - set shadowBlur(num value) => _shadowBlur = value.toJS; + external void scale(num x, num y); + external void clearRect(num x, num y, num width, num height); + external void translate(num x, num y); + external void rotate(num angle); + external void bezierCurveTo(num cp1x, num cp1y, num cp2x, num cp2y, num x, num y); + external void quadraticCurveTo(num cpx, num cpy, num x, num y); + external set globalCompositeOperation(String value); + external set lineCap(String value); + external set lineJoin(String value); + external set shadowBlur(num value); @JS('arc') - external void _arc( - JSNumber x, - JSNumber y, - JSNumber radius, - JSNumber startAngle, - JSNumber endAngle, - JSBoolean antiClockwise, - ); + external void _arc(num x, num y, num radius, num startAngle, num endAngle, bool antiClockwise); void arc(num x, num y, num radius, num startAngle, num endAngle, [bool antiClockwise = false]) => - _arc(x.toJS, y.toJS, radius.toJS, startAngle.toJS, endAngle.toJS, antiClockwise.toJS); + _arc(x, y, radius, startAngle, endAngle, antiClockwise); - @JS('filter') - external set _filter(JSString? value); - set filter(String? value) => _filter = value?.toJS; - - @JS('shadowOffsetX') - external set _shadowOffsetX(JSNumber? x); - set shadowOffsetX(num? x) => _shadowOffsetX = x?.toJS; - - @JS('shadowOffsetY') - external set _shadowOffsetY(JSNumber? y); - set shadowOffsetY(num? y) => _shadowOffsetY = y?.toJS; - - @JS('shadowColor') - external set _shadowColor(JSString? value); - set shadowColor(String? value) => _shadowColor = value?.toJS; - - @JS('ellipse') - external void _ellipse( - JSNumber x, - JSNumber y, - JSNumber radiusX, - JSNumber radiusY, - JSNumber rotation, - JSNumber startAngle, - JSNumber endAngle, - JSBoolean? antiClockwise, - ); - void ellipse( + external set filter(String? value); + external set shadowOffsetX(num? x); + external set shadowOffsetY(num? y); + external set shadowColor(String? value); + external void ellipse( num x, num y, num radiusX, @@ -1498,92 +944,55 @@ extension DomCanvasRenderingContext2DExtension on DomCanvasRenderingContext2D { num startAngle, num endAngle, bool? antiClockwise, - ) => _ellipse( - x.toJS, - y.toJS, - radiusX.toJS, - radiusY.toJS, - rotation.toJS, - startAngle.toJS, - endAngle.toJS, - antiClockwise?.toJS, ); - - @JS('strokeText') - external void _strokeText(JSString text, JSNumber x, JSNumber y); - void strokeText(String text, num x, num y) => _strokeText(text.toJS, x.toJS, y.toJS); - - @JS('globalAlpha') - external set _globalAlpha(JSNumber? value); - set globalAlpha(num? value) => _globalAlpha = value?.toJS; + external void strokeText(String text, num x, num y); + external set globalAlpha(num? value); } -@JS() -@staticInterop -class DomCanvasRenderingContextWebGl {} - -extension DomCanvasRenderingContextWebGlExtension on DomCanvasRenderingContextWebGl { - @JS('isContextLost') - external JSBoolean _isContextLost(); - bool isContextLost() => _isContextLost().toDart; +@JS('WebGLRenderingContext') +extension type DomWebGLRenderingContext._(JSObject _) implements JSObject { + external bool isContextLost(); } -@JS() -@staticInterop -class DomCanvasRenderingContextBitmapRenderer {} - -extension DomCanvasRenderingContextBitmapRendererExtension - on DomCanvasRenderingContextBitmapRenderer { +@JS('ImageBitmapRenderingContext') +extension type DomImageBitmapRenderingContext._(JSObject _) implements JSObject { external void transferFromImageBitmap(DomImageBitmap? bitmap); } @JS('ImageData') -@staticInterop -class DomImageData { - external factory DomImageData._(JSAny? data, JSNumber sw, JSNumber sh); - external factory DomImageData._empty(JSNumber sw, JSNumber sh); -} +extension type DomImageData._(JSObject _) implements JSObject { + external DomImageData(JSAny? data, int sw, int sh); + external DomImageData._empty(int sw, int sh); -DomImageData createDomImageData(Object data, int sw, int sh) => - DomImageData._(data.toJSAnyShallow, sw.toJS, sh.toJS); -DomImageData createBlankDomImageData(int sw, int sh) => DomImageData._empty(sw.toJS, sh.toJS); - -extension DomImageDataExtension on DomImageData { @JS('data') external JSUint8ClampedArray get _data; Uint8ClampedList get data => _data.toDart; } -@JS('ImageBitmap') -@staticInterop -class DomImageBitmap implements DomCanvasImageSource {} +DomImageData createDomImageData(Object data, int sw, int sh) => + DomImageData(data.toJSAnyShallow, sw, sh); +DomImageData createBlankDomImageData(int sw, int sh) => DomImageData._empty(sw, sh); -extension DomImageBitmapExtension on DomImageBitmap { - external JSNumber get width; - external JSNumber get height; +@JS('ImageBitmap') +extension type DomImageBitmap._(JSObject _) implements DomCanvasImageSource { + external int get width; + external int get height; external void close(); } -@JS() -@staticInterop -class DomCanvasPattern {} +@JS('CanvasPattern') +extension type DomCanvasPattern._(JSObject _) implements JSObject {} -@JS() -@staticInterop -class DomCanvasGradient {} - -extension DomCanvasGradientExtension on DomCanvasGradient { - @JS('addColorStop') - external void _addColorStop(JSNumber offset, JSString color); - void addColorStop(num offset, String color) => _addColorStop(offset.toJS, color.toJS); +@JS('CanvasGradient') +extension type DomCanvasGradient._(JSObject _) implements JSObject { + external void addColorStop(num offset, String color); } -@JS() -@staticInterop -class DomXMLHttpRequestEventTarget extends DomEventTarget {} +@JS('XMLHttpRequestEventTarget') +extension type DomXMLHttpRequestEventTarget._(JSObject _) implements DomEventTarget {} Future rawHttpGet(String url) => - js_util.promiseToFuture(domWindow._fetch(url.toJS)); + domWindow._fetch(url).toDart.then((JSAny? value) => value! as DomResponse); typedef MockHttpFetchResponseFactory = Future Function(String url); @@ -1617,16 +1026,17 @@ Future httpFetch(String url) async { } } -Future _rawHttpPost(String url, String data) => js_util.promiseToFuture( - domWindow._fetch( - url.toJS, - { - 'method': 'POST', - 'headers': {'Content-Type': 'text/plain'}, - 'body': data, - }.toJSAnyDeep, - ), -); +Future _rawHttpPost(String url, String data) => domWindow + ._fetch( + url, + { + 'method': 'POST', + 'headers': {'Content-Type': 'text/plain'}, + 'body': data, + }.toJSAnyDeep, + ) + .toDart + .then((JSAny? value) => value! as DomResponse); /// Sends a [data] string as HTTP POST request to [url]. /// @@ -1698,7 +1108,7 @@ extension HttpFetchResponseExtension on HttpFetchResponse { /// /// Combined with [HttpFetchResponse.contentLength], this can be used to /// implement various "progress bar" functionality. - Future read(HttpFetchReader reader) { + Future read(HttpFetchReader reader) { return payload.read(reader); } @@ -1796,7 +1206,7 @@ abstract class HttpFetchPayload { /// /// Combined with [HttpFetchResponse.contentLength], this can be used to /// implement various "progress bar" functionality. - Future read(HttpFetchReader reader); + Future read(HttpFetchReader reader); /// Returns the data as a [ByteBuffer]. Future asByteBuffer(); @@ -1814,7 +1224,7 @@ class HttpFetchPayloadImpl implements HttpFetchPayload { final DomResponse _domResponse; @override - Future read(HttpFetchReader callback) async { + Future read(HttpFetchReader callback) async { final _DomReadableStream stream = _domResponse.body; final _DomStreamReader reader = stream.getReader(); @@ -1823,15 +1233,13 @@ class HttpFetchPayloadImpl implements HttpFetchPayload { if (chunk.done) { break; } - callback(chunk.value as T); + callback(chunk.value! as JSUint8Array); } } /// Returns the data as a [ByteBuffer]. @override - Future asByteBuffer() async { - return (await _domResponse.arrayBuffer())! as ByteBuffer; - } + Future asByteBuffer() => _domResponse.arrayBuffer(); /// Returns the data parsed as JSON. @override @@ -1853,7 +1261,7 @@ class MockHttpFetchPayload implements HttpFetchPayload { final int _chunkSize; @override - Future read(HttpFetchReader callback) async { + Future read(HttpFetchReader callback) async { final int totalLength = _byteBuffer.lengthInBytes; int currentIndex = 0; while (currentIndex < totalLength) { @@ -1863,7 +1271,7 @@ class MockHttpFetchPayload implements HttpFetchPayload { currentIndex, currentIndex + chunkSize, ); - callback(chunk.toJS as T); + callback(chunk.toJS); currentIndex += chunkSize; } } @@ -1928,14 +1336,9 @@ class HttpFetchError implements Exception { } } -@JS() -@staticInterop -class DomResponse {} - -extension DomResponseExtension on DomResponse { - @JS('status') - external JSNumber get _status; - int get status => _status.toDartInt; +@JS('Response') +extension type DomResponse._(JSObject _) implements JSObject { + external int get status; external DomHeaders get headers; @@ -1943,125 +1346,69 @@ extension DomResponseExtension on DomResponse { @JS('arrayBuffer') external JSPromise _arrayBuffer(); - Future arrayBuffer() => js_util.promiseToFuture(_arrayBuffer()); + Future arrayBuffer() => + _arrayBuffer().toDart.then((JSAny? value) => (value! as JSArrayBuffer).toDart); @JS('json') external JSPromise _json(); - Future json() => js_util.promiseToFuture(_json()); + Future json() => _json().toDart; @JS('text') external JSPromise _text(); - Future text() => js_util.promiseToFuture(_text()); + Future text() => _text().toDart.then((JSAny? value) => (value! as JSString).toDart); } -@JS() -@staticInterop -class DomHeaders {} - -extension DomHeadersExtension on DomHeaders { - @JS('get') - external JSString? _get(JSString? headerName); - String? get(String? headerName) => _get(headerName?.toJS)?.toDart; +@JS('Headers') +extension type DomHeaders._(JSObject _) implements JSObject { + external String? get(String? headerName); } -@JS() -@staticInterop -class _DomReadableStream {} - -extension _DomReadableStreamExtension on _DomReadableStream { +extension type _DomReadableStream._(JSObject _) implements JSObject { external _DomStreamReader getReader(); } -@JS() -@staticInterop -class _DomStreamReader {} - -extension _DomStreamReaderExtension on _DomStreamReader { +extension type _DomStreamReader._(JSObject _) implements JSObject { @JS('read') external JSPromise _read(); - Future<_DomStreamChunk> read() => js_util.promiseToFuture<_DomStreamChunk>(_read()); + Future<_DomStreamChunk> read() => + _read().toDart.then((JSAny? value) => value! as _DomStreamChunk); } -@JS() -@staticInterop -class _DomStreamChunk {} - -extension _DomStreamChunkExtension on _DomStreamChunk { +extension type _DomStreamChunk._(JSObject _) implements JSObject { external JSAny? get value; - - @JS('done') - external JSBoolean get _done; - bool get done => _done.toDart; + external bool get done; } -@JS() -@staticInterop -class DomCharacterData extends DomNode {} +@JS('CharacterData') +extension type DomCharacterData._(JSObject _) implements DomNode {} -@JS() -@staticInterop -class DomText extends DomCharacterData {} +@JS('Text') +extension type DomText._(JSObject _) implements DomCharacterData {} DomText createDomText(String data) => domDocument.createTextNode(data); -@JS() -@staticInterop -class DomTextMetrics {} - -extension DomTextMetricsExtension on DomTextMetrics { - @JS('width') - external JSNumber? get _width; - double? get width => _width?.toDartDouble; +@JS('TextMetrics') +extension type DomTextMetrics._(JSObject _) implements JSObject { + external double? get width; } -@JS() -@staticInterop -class DomException { +@JS('DOMException') +extension type DomException._(JSObject _) implements JSObject { static const String notSupported = 'NotSupportedError'; + + external String get name; } -extension DomExceptionExtension on DomException { - @JS('name') - external JSString get _name; - String get name => _name.toDart; -} - -@JS() -@staticInterop -class DomRectReadOnly {} - -extension DomRectReadOnlyExtension on DomRectReadOnly { - @JS('x') - external JSNumber get _x; - double get x => _x.toDartDouble; - - @JS('y') - external JSNumber get _y; - double get y => _y.toDartDouble; - - @JS('width') - external JSNumber get _width; - double get width => _width.toDartDouble; - - @JS('height') - external JSNumber get _height; - double get height => _height.toDartDouble; - - @JS('top') - external JSNumber get _top; - double get top => _top.toDartDouble; - - @JS('right') - external JSNumber get _right; - double get right => _right.toDartDouble; - - @JS('bottom') - external JSNumber get _bottom; - double get bottom => _bottom.toDartDouble; - - @JS('left') - external JSNumber get _left; - double get left => _left.toDartDouble; +@JS('DOMRectReadOnly') +extension type DomRectReadOnly._(JSObject _) implements JSObject { + external double get x; + external double get y; + external double get width; + external double get height; + external double get top; + external double get right; + external double get bottom; + external double get left; } DomRect createDomRectFromPoints(DomPoint a, DomPoint b) { @@ -2069,53 +1416,37 @@ DomRect createDomRectFromPoints(DomPoint a, DomPoint b) { final num width = math.max(a.x, b.x) - left; final num top = math.min(a.y, b.y); final num height = math.max(a.y, b.y) - top; - return DomRect(left.toJS, top.toJS, width.toJS, height.toJS); + return DomRect(left, top, width, height); } @JS('DOMRect') -@staticInterop -class DomRect extends DomRectReadOnly { - external factory DomRect(JSNumber left, JSNumber top, JSNumber width, JSNumber height); +extension type DomRect._(JSObject _) implements DomRectReadOnly { + external DomRect(num left, num top, num width, num height); } @JS('FontFace') -@staticInterop -class DomFontFace { - external factory DomFontFace._args2(JSString family, JSAny source); - external factory DomFontFace._args3(JSString family, JSAny source, JSAny descriptors); +extension type DomFontFace._primary(JSObject _) implements JSObject { + external DomFontFace._(String family, JSAny source, [JSAny descriptors]); + + @JS('load') + external JSPromise _load(); + Future load() => _load().toDart.then((JSAny? value) => value! as DomFontFace); + + external String? get family; + external String? get weight; + external String? get status; } DomFontFace createDomFontFace(String family, Object source, [Map? descriptors]) { if (descriptors == null) { - return DomFontFace._args2(family.toJS, source.toJSAnyShallow); + return DomFontFace._(family, source.toJSAnyShallow); } else { - return DomFontFace._args3(family.toJS, source.toJSAnyShallow, descriptors.toJSAnyDeep); + return DomFontFace._(family, source.toJSAnyShallow, descriptors.toJSAnyDeep); } } -extension DomFontFaceExtension on DomFontFace { - @JS('load') - external JSPromise _load(); - Future load() => js_util.promiseToFuture(_load()); - - @JS('family') - external JSString? get _family; - String? get family => _family?.toDart; - - @JS('weight') - external JSString? get _weight; - String? get weight => _weight?.toDart; - - @JS('status') - external JSString? get _status; - String? get status => _status?.toDart; -} - -@JS() -@staticInterop -class DomFontFaceSet extends DomEventTarget {} - -extension DomFontFaceSetExtension on DomFontFaceSet { +@JS('FontFaceSet') +extension type DomFontFaceSet._(JSObject _) implements DomEventTarget { external DomFontFaceSet? add(DomFontFace font); external void clear(); @@ -2127,277 +1458,159 @@ extension DomFontFaceSetExtension on DomFontFaceSet { typedef DomFontFaceSetForEachCallback = void Function(DomFontFace fontFace, DomFontFace fontFaceAgain, DomFontFaceSet set); -@JS() -@staticInterop -class DomVisualViewport extends DomEventTarget {} - -extension DomVisualViewportExtension on DomVisualViewport { - @JS('height') - external JSNumber? get _height; - double? get height => _height?.toDartDouble; - - @JS('width') - external JSNumber? get _width; - double? get width => _width?.toDartDouble; - - @JS('scale') - external JSNumber? get _scale; - double? get scale => _scale?.toDartDouble; +@JS('VisualViewport') +extension type DomVisualViewport._(JSObject _) implements DomEventTarget { + external double? get height; + external double? get width; + external double? get scale; } -@JS() -@staticInterop -class DomHTMLTextAreaElement extends DomHTMLElement {} +@JS('HTMLTextAreaElement') +extension type DomHTMLTextAreaElement._(JSObject _) implements DomHTMLElement { + external set value(String? value); + external void select(); + external String get placeholder; + external set placeholder(String? value); + external String name; + external String? get selectionDirection; + external double? get selectionStart; + external double? get selectionEnd; + external set selectionStart(double? value); + external set selectionEnd(double? value); + external String? get value; + + @JS('setSelectionRange') + external void _setSelectionRange(int start, int end, [String direction]); + void setSelectionRange(int start, int end, [String? direction]) { + if (direction == null) { + _setSelectionRange(start, end); + } else { + _setSelectionRange(start, end, direction); + } + } +} DomHTMLTextAreaElement createDomHTMLTextAreaElement() => domDocument.createElement('textarea') as DomHTMLTextAreaElement; -extension DomHTMLTextAreaElementExtension on DomHTMLTextAreaElement { - @JS('value') - external set _value(JSString? value); - set value(String? value) => _value = value?.toJS; - - external void select(); - - @JS('placeholder') - external set _placeholder(JSString? value); - set placeholder(String? value) => _placeholder = value?.toJS; - - @JS('name') - external set _name(JSString value); - set name(String value) => _name = value.toJS; - - @JS('selectionDirection') - external JSString? get _selectionDirection; - String? get selectionDirection => _selectionDirection?.toDart; - - @JS('selectionStart') - external JSNumber? get _selectionStart; - double? get selectionStart => _selectionStart?.toDartDouble; - - @JS('selectionEnd') - external JSNumber? get _selectionEnd; - double? get selectionEnd => _selectionEnd?.toDartDouble; - - @JS('selectionStart') - external set _selectionStart(JSNumber? value); - set selectionStart(double? value) => _selectionStart = value?.toJS; - - @JS('selectionEnd') - external set _selectionEnd(JSNumber? value); - set selectionEnd(double? value) => _selectionEnd = value?.toJS; - - @JS('value') - external JSString? get _value; - String? get value => _value?.toDart; - - @JS('setSelectionRange') - external void _setSelectionRange(JSNumber start, JSNumber end, [JSString direction]); - void setSelectionRange(int start, int end, [String? direction]) { - if (direction == null) { - _setSelectionRange(start.toJS, end.toJS); - } else { - _setSelectionRange(start.toJS, end.toJS, direction.toJS); - } - } - - @JS('name') - external JSString get _name; - String get name => _name.toDart; - - @JS('placeholder') - external JSString get _placeholder; - String get placeholder => _placeholder.toDart; -} - -@JS() -@staticInterop -class DomClipboard extends DomEventTarget {} - -extension DomClipboardExtension on DomClipboard { +@JS('Clipboard') +extension type DomClipboard._(JSObject _) implements DomEventTarget { @JS('readText') external JSPromise _readText(); - Future readText() => js_util.promiseToFuture(_readText()); + Future readText() => + _readText().toDart.then((JSAny? value) => (value! as JSString).toDart); @JS('writeText') - external JSPromise _writeText(JSString data); - Future writeText(String data) => js_util.promiseToFuture(_writeText(data.toJS)); + external JSPromise _writeText(String data); + Future writeText(String data) => _writeText(data).toDart; } -@JS() -@staticInterop -class DomUIEvent extends DomEvent {} +@JS('UIEvent') +extension type DomUIEvent._(JSObject _) implements DomEvent {} @JS('KeyboardEvent') -@staticInterop -class DomKeyboardEvent extends DomUIEvent { - external factory DomKeyboardEvent(JSString type, [JSAny initDict]); -} +extension type DomKeyboardEvent._(JSObject _) implements DomUIEvent { + external DomKeyboardEvent(String type, [JSAny initDict]); -extension DomKeyboardEventExtension on DomKeyboardEvent { - @JS('altKey') - external JSBoolean get _altKey; - bool get altKey => _altKey.toDart; - - @JS('code') - external JSString? get _code; - String? get code => _code?.toDart; - - @JS('ctrlKey') - external JSBoolean get _ctrlKey; - bool get ctrlKey => _ctrlKey.toDart; - - @JS('key') - external JSString? get _key; - String? get key => _key?.toDart; - - @JS('keyCode') - external JSNumber get _keyCode; - double get keyCode => _keyCode.toDartDouble; - - @JS('location') - external JSNumber get _location; - double get location => _location.toDartDouble; - - @JS('metaKey') - external JSBoolean get _metaKey; - bool get metaKey => _metaKey.toDart; - - @JS('repeat') - external JSBoolean? get _repeat; - bool? get repeat => _repeat?.toDart; + external bool get altKey; + external String? get code; + external bool get ctrlKey; + external String? get key; + external double get keyCode; + external double get location; + external bool get metaKey; + external bool? get repeat; // Safari injects synthetic keyboard events after auto-complete that don't // have a `shiftKey` attribute, so this property must be nullable. - @JS('shiftKey') - external JSBoolean? get _shiftKey; - bool? get shiftKey => _shiftKey?.toDart; - - @JS('isComposing') - external JSBoolean get _isComposing; - bool get isComposing => _isComposing.toDart; - - @JS('getModifierState') - external JSBoolean _getModifierState(JSString keyArg); - bool getModifierState(String keyArg) => _getModifierState(keyArg.toJS).toDart; + external bool? get shiftKey; + external bool get isComposing; + external bool getModifierState(String keyArg); } DomKeyboardEvent createDomKeyboardEvent(String type, [Map? init]) { if (init == null) { - return DomKeyboardEvent(type.toJS); + return DomKeyboardEvent(type); } else { - return DomKeyboardEvent(type.toJS, init.toJSAnyDeep); + return DomKeyboardEvent(type, init.toJSAnyDeep); } } -@JS() -@staticInterop -class DomHistory {} - -extension DomHistoryExtension on DomHistory { +@JS('History') +extension type DomHistory._(JSObject _) implements JSObject { @JS('state') external JSAny? get _state; dynamic get state => _state?.toObjectDeep; @JS('go') - external void _go([JSNumber delta]); + external void _go([int delta]); void go([int? delta]) { if (delta == null) { _go(); } else { - _go(delta.toJS); + _go(delta); } } @JS('pushState') - external void _pushState(JSAny? data, JSString title, JSString? url); + external void _pushState(JSAny? data, String title, String? url); void pushState(Object? data, String title, String? url) => - _pushState(data?.toJSAnyDeep, title.toJS, url?.toJS); + _pushState(data?.toJSAnyDeep, title, url); @JS('replaceState') - external void _replaceState(JSAny? data, JSString title, JSString? url); + external void _replaceState(JSAny? data, String title, String? url); void replaceState(Object? data, String title, String? url) => - _replaceState(data?.toJSAnyDeep, title.toJS, url?.toJS); + _replaceState(data?.toJSAnyDeep, title, url); } -@JS() -@staticInterop -class DomLocation {} - -extension DomLocationExtension on DomLocation { - @JS('pathname') - external JSString? get _pathname; - String? get pathname => _pathname?.toDart; - - @JS('search') - external JSString? get _search; - String? get search => _search?.toDart; - - @JS('hash') - external JSString get _hash; - // We have to change the name here because 'hash' is inherited from [Object]. - String get locationHash => _hash.toDart; - - @JS('origin') - external JSString get _origin; - String get origin => _origin.toDart; - - @JS('href') - external JSString get _href; - String get href => _href.toDart; +@JS('Location') +extension type DomLocation._(JSObject _) implements JSObject { + external String? get pathname; + external String? get search; + external String get hash; + external String get origin; + external String get href; } @JS('PopStateEvent') -@staticInterop -class DomPopStateEvent extends DomEvent { - external factory DomPopStateEvent(JSString type, [JSAny initDict]); -} +extension type DomPopStateEvent._(JSObject _) implements DomEvent { + external DomPopStateEvent(String type, [JSAny initDict]); -DomPopStateEvent createDomPopStateEvent(String type, Map? eventInitDict) { - if (eventInitDict == null) { - return DomPopStateEvent(type.toJS); - } else { - return DomPopStateEvent(type.toJS, eventInitDict.toJSAnyDeep); - } -} - -extension DomPopStateEventExtension on DomPopStateEvent { @JS('state') external JSAny? get _state; dynamic get state => _state?.toObjectDeep; } -@JS('URL') -@staticInterop -class DomURL { - external factory DomURL(JSString url, [JSString? base]); +DomPopStateEvent createDomPopStateEvent(String type, Map? eventInitDict) { + if (eventInitDict == null) { + return DomPopStateEvent(type); + } else { + return DomPopStateEvent(type, eventInitDict.toJSAnyDeep); + } } -DomURL createDomURL(String url, [String? base]) => - base == null ? DomURL(url.toJS) : DomURL(url.toJS, base.toJS); +@JS('URL') +extension type DomURL._(JSObject _) implements JSObject { + external DomURL(String url, [String? base]); -extension DomURLExtension on DomURL { @JS('createObjectURL') - external JSString _createObjectURL(JSAny object); - String createObjectURL(Object object) => _createObjectURL(object.toJSAnyShallow).toDart; + external String _createObjectURL(JSAny object); + String createObjectURL(Object object) => _createObjectURL(object.toJSAnyShallow); - @JS('revokeObjectURL') - external void _revokeObjectURL(JSString url); - void revokeObjectURL(String url) => _revokeObjectURL(url.toJS); + external void revokeObjectURL(String url); @JS('toString') - external JSString toJSString(); + external String toJSString(); } +DomURL createDomURL(String url, [String? base]) => base == null ? DomURL(url) : DomURL(url, base); + @JS('Blob') -@staticInterop -class DomBlob { - external factory DomBlob(JSArray parts); +extension type DomBlob._(JSObject _) implements JSObject { + external DomBlob(JSArray parts); - external factory DomBlob.withOptions(JSArray parts, JSAny options); -} + external DomBlob.withOptions(JSArray parts, JSAny options); -extension DomBlobExtension on DomBlob { external JSPromise arrayBuffer(); } @@ -2412,15 +1625,9 @@ DomBlob createDomBlob(List parts, [Map? options]) { typedef DomMutationCallback = void Function(JSArray mutation, DomMutationObserver observer); @JS('MutationObserver') -@staticInterop -class DomMutationObserver { - external factory DomMutationObserver(JSFunction callback); -} +extension type DomMutationObserver._(JSObject _) implements JSObject { + external DomMutationObserver(JSFunction callback); -DomMutationObserver createDomMutationObserver(DomMutationCallback callback) => - DomMutationObserver(callback.toJS); - -extension DomMutationObserverExtension on DomMutationObserver { external void disconnect(); @JS('observe') @@ -2435,11 +1642,11 @@ extension DomMutationObserverExtension on DomMutationObserver { } } -@JS() -@staticInterop -class DomMutationRecord {} +DomMutationObserver createDomMutationObserver(DomMutationCallback callback) => + DomMutationObserver(callback.toJS); -extension DomMutationRecordExtension on DomMutationRecord { +@JS() +extension type DomMutationRecord._(JSObject _) implements JSObject { @JS('addedNodes') external _DomList? get _addedNodes; Iterable? get addedNodes { @@ -2460,45 +1667,25 @@ extension DomMutationRecordExtension on DomMutationRecord { return createDomListWrapper(list); } - @JS('attributeName') - external JSString? get _attributeName; - String? get attributeName => _attributeName?.toDart; - - @JS('type') - external JSString? get _type; - String? get type => _type?.toDart; + external String? get attributeName; + external String? get type; } -@JS() -@staticInterop -class DomMediaQueryList extends DomEventTarget {} - -extension DomMediaQueryListExtension on DomMediaQueryList { - @JS('matches') - external JSBoolean get _matches; - bool get matches => _matches.toDart; - - @JS('addListener') +@JS('MediaQueryList') +extension type DomMediaQueryList._(JSObject _) implements DomEventTarget { + external bool get matches; external void addListener(DomEventListener? listener); - - @JS('removeListener') external void removeListener(DomEventListener? listener); } -@JS() -@staticInterop -class DomMediaQueryListEvent extends DomEvent {} - -extension DomMediaQueryListEventExtension on DomMediaQueryListEvent { - @JS('matches') - external JSBoolean? get _matches; - bool? get matches => _matches?.toDart; +@JS('MediaQueryListEvent') +extension type DomMediaQueryListEvent._(JSObject _) implements DomEvent { + external bool? get matches; } @JS('Path2D') -@staticInterop -class DomPath2D { - external factory DomPath2D([JSAny path]); +extension type DomPath2D._(JSObject _) implements JSObject { + external DomPath2D([JSAny path]); } DomPath2D createDomPath2D([Object? path]) { @@ -2510,112 +1697,60 @@ DomPath2D createDomPath2D([Object? path]) { } @JS('InputEvent') -@staticInterop -class DomInputEvent extends DomUIEvent { - external factory DomInputEvent(JSString type, [JSAny initDict]); +extension type DomInputEvent._(JSObject _) implements DomUIEvent { + external DomInputEvent(String type, [JSAny initDict]); } @JS('FocusEvent') -@staticInterop -class DomFocusEvent extends DomUIEvent {} - -extension DomFocusEventExtension on DomFocusEvent { +extension type DomFocusEvent._(JSObject _) implements DomUIEvent { external DomEventTarget? get relatedTarget; } @JS('MouseEvent') -@staticInterop -class DomMouseEvent extends DomUIEvent { - external factory DomMouseEvent(JSString type, [JSAny initDict]); -} +extension type DomMouseEvent._(JSObject _) implements DomUIEvent { + external DomMouseEvent(String type, [JSAny initDict]); -extension DomMouseEventExtension on DomMouseEvent { - @JS('clientX') - external JSNumber get _clientX; - double get clientX => _clientX.toDartDouble; - - @JS('clientY') - external JSNumber get _clientY; - double get clientY => _clientY.toDartDouble; - - @JS('offsetX') - external JSNumber get _offsetX; - double get offsetX => _offsetX.toDartDouble; - - @JS('offsetY') - external JSNumber get _offsetY; - double get offsetY => _offsetY.toDartDouble; - - @JS('pageX') - external JSNumber get _pageX; - double get pageX => _pageX.toDartDouble; - - @JS('pageY') - external JSNumber get _pageY; - double get pageY => _pageY.toDartDouble; + external double get clientX; + external double get clientY; + external double get offsetX; + external double get offsetY; + external double get pageX; + external double get pageY; DomPoint get client => DomPoint(clientX, clientY); DomPoint get offset => DomPoint(offsetX, offsetY); - @JS('button') - external JSNumber get _button; - double get button => _button.toDartDouble; - - @JS('buttons') - external JSNumber? get _buttons; - double? get buttons => _buttons?.toDartDouble; - - @JS('ctrlKey') - external JSBoolean get _ctrlKey; - bool get ctrlKey => _ctrlKey.toDart; - - @JS('getModifierState') - external JSBoolean _getModifierState(JSString keyArg); - bool getModifierState(String keyArg) => _getModifierState(keyArg.toJS).toDart; + external double get button; + external double? get buttons; + external bool get ctrlKey; + external bool getModifierState(String keyArg); } DomMouseEvent createDomMouseEvent(String type, [Map? init]) { if (init == null) { - return DomMouseEvent(type.toJS); + return DomMouseEvent(type); } else { - return DomMouseEvent(type.toJS, init.toJSAnyDeep); + return DomMouseEvent(type, init.toJSAnyDeep); } } DomInputEvent createDomInputEvent(String type, [Map? init]) { if (init == null) { - return DomInputEvent(type.toJS); + return DomInputEvent(type); } else { - return DomInputEvent(type.toJS, init.toJSAnyDeep); + return DomInputEvent(type, init.toJSAnyDeep); } } @JS('PointerEvent') -@staticInterop -class DomPointerEvent extends DomMouseEvent { - external factory DomPointerEvent(JSString type, [JSAny initDict]); -} +extension type DomPointerEvent._(JSObject _) implements DomMouseEvent { + external DomPointerEvent(String type, [JSAny initDict]); -extension DomPointerEventExtension on DomPointerEvent { - @JS('pointerId') - external JSNumber? get _pointerId; - double? get pointerId => _pointerId?.toDartDouble; - - @JS('pointerType') - external JSString? get _pointerType; - String? get pointerType => _pointerType?.toDart; - - @JS('pressure') - external JSNumber? get _pressure; - double? get pressure => _pressure?.toDartDouble; - - @JS('tiltX') - external JSNumber? get _tiltX; - double? get tiltX => _tiltX?.toDartDouble; - - @JS('tiltY') - external JSNumber? get _tiltY; - double? get tiltY => _tiltY?.toDartDouble; + external double? get pointerId; + external String? get pointerType; + external double? get pressure; + external double? get tiltX; + external double? get tiltY; @JS('getCoalescedEvents') external JSArray _getCoalescedEvents(); @@ -2625,94 +1760,52 @@ extension DomPointerEventExtension on DomPointerEvent { DomPointerEvent createDomPointerEvent(String type, [Map? init]) { if (init == null) { - return DomPointerEvent(type.toJS); + return DomPointerEvent(type); } else { - return DomPointerEvent(type.toJS, init.toJSAnyDeep); + return DomPointerEvent(type, init.toJSAnyDeep); } } @JS('WheelEvent') -@staticInterop -class DomWheelEvent extends DomMouseEvent { - external factory DomWheelEvent(JSString type, [JSAny initDict]); -} +extension type DomWheelEvent._(JSObject _) implements DomMouseEvent { + external DomWheelEvent(String type, [JSAny initDict]); -extension DomWheelEventExtension on DomWheelEvent { - @JS('deltaX') - external JSNumber get _deltaX; - double get deltaX => _deltaX.toDartDouble; - - @JS('deltaY') - external JSNumber get _deltaY; - double get deltaY => _deltaY.toDartDouble; - - @JS('wheelDeltaX') - external JSNumber? get _wheelDeltaX; - double? get wheelDeltaX => _wheelDeltaX?.toDartDouble; - - @JS('wheelDeltaY') - external JSNumber? get _wheelDeltaY; - double? get wheelDeltaY => _wheelDeltaY?.toDartDouble; - - @JS('deltaMode') - external JSNumber get _deltaMode; - double get deltaMode => _deltaMode.toDartDouble; + external double get deltaX; + external double get deltaY; + external double? get wheelDeltaX; + external double? get wheelDeltaY; + external double get deltaMode; } DomWheelEvent createDomWheelEvent(String type, [Map? init]) { if (init == null) { - return DomWheelEvent(type.toJS); + return DomWheelEvent(type); } else { - return DomWheelEvent(type.toJS, init.toJSAnyDeep); + return DomWheelEvent(type, init.toJSAnyDeep); } } @JS('TouchEvent') -@staticInterop -class DomTouchEvent extends DomUIEvent { - external factory DomTouchEvent(JSString type, [JSAny initDict]); -} +extension type DomTouchEvent._(JSObject _) implements DomUIEvent { + external DomTouchEvent(String type, [JSAny initDict]); -extension DomTouchEventExtension on DomTouchEvent { - @JS('altKey') - external JSBoolean get _altKey; - bool get altKey => _altKey.toDart; - - @JS('ctrlKey') - external JSBoolean get _ctrlKey; - bool get ctrlKey => _ctrlKey.toDart; - - @JS('metaKey') - external JSBoolean get _metaKey; - bool get metaKey => _metaKey.toDart; - - @JS('shiftKey') - external JSBoolean get _shiftKey; - bool get shiftKey => _shiftKey.toDart; + external bool get altKey; + external bool get ctrlKey; + external bool get metaKey; + external bool get shiftKey; @JS('changedTouches') - external _DomTouchList get _changedTouches; - Iterable get changedTouches => createDomTouchListWrapper(_changedTouches); + external _DomList get _changedTouches; + Iterable get changedTouches => createDomListWrapper(_changedTouches); } @JS('Touch') -@staticInterop -class DomTouch { - external factory DomTouch([JSAny initDict]); -} +extension type DomTouch._(JSObject _) implements JSObject { + external DomTouch([JSAny initDict]); -extension DomTouchExtension on DomTouch { - @JS('identifier') - external JSNumber? get _identifier; - double? get identifier => _identifier?.toDartDouble; - - @JS('clientX') - external JSNumber get _clientX; - double get clientX => _clientX.toDartDouble; - - @JS('clientY') - external JSNumber get _clientY; - double get clientY => _clientY.toDartDouble; + external double? get identifier; + external double get clientX; + external double get clientY; DomPoint get client => DomPoint(clientX, clientY); } @@ -2726,22 +1819,17 @@ DomTouch createDomTouch([Map? init]) { } @JS('CompositionEvent') -@staticInterop -class DomCompositionEvent extends DomUIEvent { - external factory DomCompositionEvent(JSString type, [JSAny initDict]); -} +extension type DomCompositionEvent._(JSObject _) implements DomUIEvent { + external DomCompositionEvent(String type, [JSAny initDict]); -extension DomCompositionEventExtension on DomCompositionEvent { - @JS('data') - external JSString? get _data; - String? get data => _data?.toDart; + external String? get data; } DomCompositionEvent createDomCompositionEvent(String type, [Map? options]) { if (options == null) { - return DomCompositionEvent(type.toJS); + return DomCompositionEvent(type); } else { - return DomCompositionEvent(type.toJS, options.toJSAnyDeep); + return DomCompositionEvent(type, options.toJSAnyDeep); } } @@ -2755,191 +1843,75 @@ DomCompositionEvent createDomCompositionEvent(String type, [Map _disabled?.toDart; - - @JS('disabled') - external set _disabled(JSBoolean? value); - set disabled(bool? value) => _disabled = value?.toJS; +extension type DomElementWithDisabledProperty._(JSObject _) implements DomHTMLElement { + external bool? disabled; } -@JS() -@staticInterop -class DomHTMLInputElement extends DomHTMLElement {} - -extension DomHTMLInputElementExtension on DomHTMLInputElement { - @JS('type') - external set _type(JSString? value); - set type(String? value) => _type = value?.toJS; - - @JS('max') - external set _max(JSString? value); - set max(String? value) => _max = value?.toJS; - - @JS('min') - external set _min(JSString value); - set min(String value) => _min = value.toJS; - - @JS('value') - external set _value(JSString? value); - set value(String? v) => _value = v?.toJS; - - @JS('value') - external JSString? get _value; - String? get value => _value?.toDart; - - @JS('disabled') - external JSBoolean? get _disabled; - bool? get disabled => _disabled?.toDart; - - @JS('disabled') - external set _disabled(JSBoolean? value); - set disabled(bool? value) => _disabled = value?.toJS; - - @JS('placeholder') - external set _placeholder(JSString? value); - set placeholder(String? value) => _placeholder = value?.toJS; - - @JS('name') - external set _name(JSString? value); - set name(String? value) => _name = value?.toJS; - - @JS('autocomplete') - external set _autocomplete(JSString value); - set autocomplete(String value) => _autocomplete = value.toJS; - - @JS('selectionDirection') - external JSString? get _selectionDirection; - String? get selectionDirection => _selectionDirection?.toDart; - - @JS('selectionStart') - external JSNumber? get _selectionStart; - double? get selectionStart => _selectionStart?.toDartDouble; - - @JS('selectionEnd') - external JSNumber? get _selectionEnd; - double? get selectionEnd => _selectionEnd?.toDartDouble; - - @JS('selectionStart') - external set _selectionStart(JSNumber? value); - set selectionStart(double? value) => _selectionStart = value?.toJS; - - @JS('selectionEnd') - external set _selectionEnd(JSNumber? value); - set selectionEnd(double? value) => _selectionEnd = value?.toJS; +@JS('HTMLInputElement') +extension type DomHTMLInputElement._(JSObject _) implements DomHTMLElement { + external String? type; + external set max(String? value); + external set min(String value); + external String? value; + external bool? disabled; + external String placeholder; + external String? name; + external String autocomplete; + external String? get selectionDirection; + external double? selectionStart; + external double? selectionEnd; @JS('setSelectionRange') - external void _setSelectionRange(JSNumber start, JSNumber end, [JSString direction]); + external void _setSelectionRange(int start, int end, [String direction]); void setSelectionRange(int start, int end, [String? direction]) { if (direction == null) { - _setSelectionRange(start.toJS, end.toJS); + _setSelectionRange(start, end); } else { - _setSelectionRange(start.toJS, end.toJS, direction.toJS); + _setSelectionRange(start, end, direction); } } - - @JS('autocomplete') - external JSString get _autocomplete; - String get autocomplete => _autocomplete.toDart; - - @JS('name') - external JSString? get _name; - String? get name => _name?.toDart; - - @JS('type') - external JSString? get _type; - String? get type => _type?.toDart; - - @JS('placeholder') - external JSString get _placeholder; - String get placeholder => _placeholder.toDart; } DomHTMLInputElement createDomHTMLInputElement() => domDocument.createElement('input') as DomHTMLInputElement; -@JS() -@staticInterop -class DomTokenList {} - -extension DomTokenListExtension on DomTokenList { - @JS('add') - external void _add(JSString value); - void add(String value) => _add(value.toJS); - - @JS('remove') - external void _remove(JSString value); - void remove(String value) => _remove(value.toJS); - - @JS('contains') - external JSBoolean _contains(JSString token); - bool contains(String token) => _contains(token.toJS).toDart; +@JS('DOMTokenList') +extension type DomTokenList._(JSObject _) implements JSObject { + external void add(String value); + external void remove(String value); + external bool contains(String token); } -@JS() -@staticInterop -class DomHTMLFormElement extends DomHTMLElement {} - -extension DomHTMLFormElementExtension on DomHTMLFormElement { - @JS('noValidate') - external set _noValidate(JSBoolean? value); - set noValidate(bool? value) => _noValidate = value?.toJS; - - @JS('method') - external set _method(JSString? value); - set method(String? value) => _method = value?.toJS; - - @JS('action') - external set _action(JSString? value); - set action(String? value) => _action = value?.toJS; +@JS('HTMLFormElement') +extension type DomHTMLFormElement._(JSObject _) implements DomHTMLElement { + external set noValidate(bool? value); + external set method(String? value); + external set action(String? value); } DomHTMLFormElement createDomHTMLFormElement() => domDocument.createElement('form') as DomHTMLFormElement; -@JS() -@staticInterop -class DomHTMLLabelElement extends DomHTMLElement {} +@JS('HTMLLabelElement') +extension type DomHTMLLabelElement._(JSObject _) implements DomHTMLElement {} DomHTMLLabelElement createDomHTMLLabelElement() => domDocument.createElement('label') as DomHTMLLabelElement; @JS('OffscreenCanvas') -@staticInterop -class DomOffscreenCanvas extends DomEventTarget { - external factory DomOffscreenCanvas(JSNumber width, JSNumber height); -} +extension type DomOffscreenCanvas._(JSObject _) implements DomEventTarget { + external DomOffscreenCanvas(int width, int height); -extension DomOffscreenCanvasExtension on DomOffscreenCanvas { - @JS('height') - external JSNumber? get _height; - double? get height => _height?.toDartDouble; - - @JS('width') - external JSNumber? get _width; - double? get width => _width?.toDartDouble; - - @JS('height') - external set _height(JSNumber? value); - set height(double? value) => _height = value?.toJS; - - @JS('width') - external set _width(JSNumber? value); - set width(double? value) => _width = value?.toJS; + external double? height; + external double? width; @JS('getContext') - external JSAny? _getContext(JSString contextType, [JSAny attributes]); + external JSAny? _getContext(String contextType, [JSAny attributes]); Object? getContext(String contextType, [Map? attributes]) { if (attributes == null) { - return _getContext(contextType.toJS); + return _getContext(contextType); } else { - return _getContext(contextType.toJS, attributes.toJSAnyDeep); + return _getContext(contextType, attributes.toJSAnyDeep); } } @@ -2959,123 +1931,85 @@ extension DomOffscreenCanvasExtension on DomOffscreenCanvas { } else { blob = _convertToBlob(options.toJSAnyDeep); } - return js_util.promiseToFuture(blob); + return blob.toDart.then((JSAny? value) => value! as DomBlob); } - @JS('transferToImageBitmap') - external JSAny? _transferToImageBitmap(); - DomImageBitmap transferToImageBitmap() => _transferToImageBitmap()! as DomImageBitmap; + external DomImageBitmap transferToImageBitmap(); } DomOffscreenCanvas createDomOffscreenCanvas(int width, int height) => - DomOffscreenCanvas(width.toJS, height.toJS); + DomOffscreenCanvas(width, height); @JS('FileReader') -@staticInterop -class DomFileReader extends DomEventTarget { - external factory DomFileReader(); -} +extension type DomFileReader._(JSObject _) implements DomEventTarget { + external DomFileReader(); -extension DomFileReaderExtension on DomFileReader { external void readAsDataURL(DomBlob blob); } DomFileReader createDomFileReader() => DomFileReader(); -@JS() -@staticInterop -class DomDocumentFragment extends DomNode {} - -extension DomDocumentFragmentExtension on DomDocumentFragment { +@JS('DocumentFragment') +extension type DomDocumentFragment._(JSObject _) implements DomNode { external DomElement? get firstElementChild; external DomElement? get lastElementChild; external void prepend(DomNode node); - - @JS('querySelector') - external DomElement? _querySelector(JSString selectors); - DomElement? querySelector(String selectors) => _querySelector(selectors.toJS); + external DomElement? querySelector(String selectors); @JS('querySelectorAll') - external _DomList _querySelectorAll(JSString selectors); + external _DomList _querySelectorAll(String selectors); Iterable querySelectorAll(String selectors) => - createDomListWrapper(_querySelectorAll(selectors.toJS)); + createDomListWrapper(_querySelectorAll(selectors)); } -@JS() -@staticInterop -class DomShadowRoot extends DomDocumentFragment {} - -extension DomShadowRootExtension on DomShadowRoot { +@JS('ShadowRoot') +extension type DomShadowRoot._(JSObject _) implements DomDocumentFragment { external DomElement? get activeElement; external DomElement? get host; - - @JS('mode') - external JSString? get _mode; - String? get mode => _mode?.toDart; - - @JS('delegatesFocus') - external JSBoolean? get _delegatesFocus; - bool? get delegatesFocus => _delegatesFocus?.toDart; - - @JS('elementFromPoint') - external DomElement? _elementFromPoint(JSNumber x, JSNumber y); - DomElement? elementFromPoint(int x, int y) => _elementFromPoint(x.toJS, y.toJS); + external String? get mode; + external bool? get delegatesFocus; + external DomElement? elementFromPoint(int x, int y); } -@JS() -@staticInterop -class DomStyleSheet {} +@JS('StyleSheet') +extension type DomStyleSheet._(JSObject _) implements JSObject {} -@JS() -@staticInterop -class DomCSSStyleSheet extends DomStyleSheet {} - -extension DomCSSStyleSheetExtension on DomCSSStyleSheet { +@JS('CSSStyleSheet') +extension type DomCSSStyleSheet._(JSObject _) implements DomStyleSheet { @JS('cssRules') external _DomList get _cssRules; Iterable get cssRules => createDomListWrapper(_cssRules); @JS('insertRule') - external JSNumber _insertRule(JSString rule, [JSNumber index]); + external double _insertRule(String rule, [int index]); double insertRule(String rule, [int? index]) { if (index == null) { - return _insertRule(rule.toJS).toDartDouble; + return _insertRule(rule); } else { - return _insertRule(rule.toJS, index.toJS).toDartDouble; + return _insertRule(rule, index); } } } -@JS() -@staticInterop -class DomCSSRule {} - -extension DomCSSRuleExtension on DomCSSRule { - @JS('cssText') - external JSString get _cssText; - String get cssText => _cssText.toDart; +@JS('CSSRule') +extension type DomCSSRule._(JSObject _) implements JSObject { + external String get cssText; } -@JS() -@staticInterop -class DomScreen {} - -extension DomScreenExtension on DomScreen { +@JS('Screen') +extension type DomScreen._(JSObject _) implements JSObject { external DomScreenOrientation? get orientation; external double get width; external double get height; } -@JS() -@staticInterop -class DomScreenOrientation extends DomEventTarget {} - -extension DomScreenOrientationExtension on DomScreenOrientation { +@JS('ScreenOrientation') +extension type DomScreenOrientation._(JSObject _) implements DomEventTarget { @JS('lock') - external JSPromise _lock(JSString orientation); - Future lock(String orientation) => js_util.promiseToFuture(_lock(orientation.toJS)); + external JSPromise _lock(String orientation); + Future lock(String orientation) => _lock(orientation).toDart; external void unlock(); } @@ -3084,17 +2018,15 @@ extension DomScreenOrientationExtension on DomScreenOrientation { // event listener of the requested type to the target. Calling [cancel] will // remove the listener. class DomSubscription { - DomSubscription(this.target, String typeString, DartDomEventListener dartListener) - : type = typeString.toJS, - listener = createDomEventListener(dartListener) { - target._addEventListener(type, listener); + DomSubscription(this.target, this.type, this.listener) { + target.addEventListener(type, listener); } - final JSString type; + final String type; final DomEventTarget target; final DomEventListener listener; - void cancel() => target._removeEventListener(type, listener); + void cancel() => target.removeEventListener(type, listener); } class DomPoint { @@ -3105,90 +2037,56 @@ class DomPoint { } @JS('WebSocket') -@staticInterop -class DomWebSocket extends DomEventTarget { - external factory DomWebSocket(JSString url); -} +extension type DomWebSocket._(JSObject _) implements DomEventTarget { + external DomWebSocket(String url); -extension DomWebSocketExtension on DomWebSocket { @JS('send') external void _send(JSAny? data); void send(Object? data) => _send(data?.toJSAnyShallow); } -DomWebSocket createDomWebSocket(String url) => DomWebSocket(url.toJS); +DomWebSocket createDomWebSocket(String url) => DomWebSocket(url); -@JS() -@staticInterop -class DomMessageEvent extends DomEvent {} - -extension DomMessageEventExtension on DomMessageEvent { +@JS('MessageEvent') +extension type DomMessageEvent._(JSObject _) implements DomEvent { @JS('data') external JSAny? get _data; dynamic get data => _data?.toObjectDeep; - @JS('origin') - external JSString get _origin; - String get origin => _origin.toDart; + external String get origin; /// The source may be a `WindowProxy`, a `MessagePort`, or a `ServiceWorker`. /// /// When a message is sent from an iframe through `window.parent.postMessage` /// the source will be a `WindowProxy` which has the same methods as [Window]. - DomMessageEventSource get source => js_util.getProperty(this, 'source'); + external JSAny? get source; - List get ports => - js_util.getProperty>(this, 'ports').cast(); + external JSArray get ports; } -@JS() -@staticInterop -class DomMessageEventSource {} - -extension DomMEssageEventSourceExtension on DomMessageEventSource { - external DomMessageEventLocation? get location; +// This is typed as JSAny? since it may come from a cross-origin iframe. +extension type DomMessageEventSource._(JSAny? _) { + external JSAny? get location; } -@JS() -@staticInterop -class DomMessageEventLocation {} - -extension DomMessageEventSourceExtension on DomMessageEventLocation { +// This is typed as JSAny? since it may come from a cross-origin iframe. +extension type DomMessageEventLocation._(JSAny? _) { external String? get href; } -@JS() -@staticInterop -class DomHTMLIFrameElement extends DomHTMLElement {} - -extension DomHTMLIFrameElementExtension on DomHTMLIFrameElement { - @JS('src') - external set _src(JSString? value); - set src(String? value) => _src = value?.toJS; - - @JS('src') - external JSString? get _src; - String? get src => _src?.toDart; - - @JS('height') - external set _height(JSString? value); - set height(String? value) => _height = value?.toJS; - - @JS('width') - external set _width(JSString? value); - set width(String? value) => _width = value?.toJS; - +@JS('HTMLIFrameElement') +extension type DomHTMLIFrameElement._(JSObject _) implements DomHTMLElement { + external String? src; + external set height(String? value); + external set width(String? value); external DomWindow get contentWindow; } DomHTMLIFrameElement createDomHTMLIFrameElement() => domDocument.createElement('iframe') as DomHTMLIFrameElement; -@JS() -@staticInterop -class DomMessagePort extends DomEventTarget {} - -extension DomMessagePortExtension on DomMessagePort { +@JS('MessagePort') +extension type DomMessagePort._(JSObject _) implements DomEventTarget { @JS('postMessage') external void _postMessage(JSAny? message); void postMessage(Object? message) => _postMessage(message?.toJSAnyDeep); @@ -3197,12 +2095,9 @@ extension DomMessagePortExtension on DomMessagePort { } @JS('MessageChannel') -@staticInterop -class DomMessageChannel { - external factory DomMessageChannel(); -} +extension type DomMessageChannel._(JSObject _) implements JSObject { + external DomMessageChannel(); -extension DomMessageChannelExtension on DomMessageChannel { external DomMessagePort get port1; external DomMessagePort get port2; } @@ -3211,9 +2106,12 @@ extension DomMessageChannelExtension on DomMessageChannel { /// /// See: https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver @JS('ResizeObserver') -@staticInterop -abstract class DomResizeObserver { - external factory DomResizeObserver(JSFunction observer); +extension type DomResizeObserver._(JSObject _) implements JSObject { + external DomResizeObserver(JSFunction observer); + + external void disconnect(); + external void observe(DomElement target, [DomResizeObserverObserveOptions options]); + external void unobserve(DomElement target); } /// Creates a DomResizeObserver with a callback. @@ -3226,23 +2124,11 @@ DomResizeObserver? createDomResizeObserver(DomResizeObserverCallbackFn fn) => Do }.toJS, ); -/// ResizeObserver instance methods. -/// -/// See: https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver#instance_methods -extension DomResizeObserverExtension on DomResizeObserver { - external void disconnect(); - external void observe(DomElement target, [DomResizeObserverObserveOptions options]); - external void unobserve(DomElement target); -} - /// Options object passed to the `observe` method of a [DomResizeObserver]. /// /// See: https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/observe#parameters -@JS() -@staticInterop -@anonymous -abstract class DomResizeObserverObserveOptions { - external factory DomResizeObserverObserveOptions({JSString box}); +extension type DomResizeObserverObserveOptions._(JSObject _) implements JSObject { + external DomResizeObserverObserveOptions({String box}); } /// Type of the function used to create a Resize Observer. @@ -3252,14 +2138,8 @@ typedef DomResizeObserverCallbackFn = /// The object passed to the [DomResizeObserverCallbackFn], which allows access to the new dimensions of the observed element. /// /// See: https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry -@JS() -@staticInterop -abstract class DomResizeObserverEntry {} - -/// ResizeObserverEntry instance properties. -/// -/// See: https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry#instance_properties -extension DomResizeObserverEntryExtension on DomResizeObserverEntry { +@JS('ResizeObserverEntry') +extension type DomResizeObserverEntry._(JSObject _) implements JSObject { /// A DOMRectReadOnly object containing the new size of the observed element when the callback is run. /// /// Note that this is better supported than the above two properties, but it @@ -3277,16 +2157,12 @@ extension DomResizeObserverEntryExtension on DomResizeObserverEntry { /// A factory to create `TrustedTypePolicy` objects. /// See: https://developer.mozilla.org/en-US/docs/Web/API/TrustedTypePolicyFactory -@JS() -@staticInterop -abstract class DomTrustedTypePolicyFactory {} - -/// A subset of TrustedTypePolicyFactory methods. -extension DomTrustedTypePolicyFactoryExtension on DomTrustedTypePolicyFactory { +@JS('TrustedTypePolicyFactory') +extension type DomTrustedTypePolicyFactory._(JSObject _) implements JSObject { /// Creates a TrustedTypePolicy object named `policyName` that implements the /// rules passed as `policyOptions`. external DomTrustedTypePolicy createPolicy( - JSString policyName, + String policyName, DomTrustedTypePolicyOptions? policyOptions, ); } @@ -3297,15 +2173,12 @@ extension DomTrustedTypePolicyFactoryExtension on DomTrustedTypePolicyFactory { /// values. /// /// See: https://developer.mozilla.org/en-US/docs/Web/API/TrustedTypePolicyFactory/createPolicy#policyoptions -@JS() -@staticInterop -@anonymous -abstract class DomTrustedTypePolicyOptions { +extension type DomTrustedTypePolicyOptions._(JSObject _) implements JSObject { /// Constructs a TrustedTypePolicyOptions object in JavaScript. /// /// `createScriptURL` is a callback function that contains code to run when /// creating a TrustedScriptURL object. - external factory DomTrustedTypePolicyOptions({JSFunction? createScriptURL}); + external DomTrustedTypePolicyOptions({JSFunction? createScriptURL}); } /// Type of the function used to configure createScriptURL. @@ -3318,18 +2191,12 @@ typedef DomCreateScriptUrlOptionFn = String? Function(String input); /// therefore this class has no constructor. /// /// See: https://developer.mozilla.org/en-US/docs/Web/API/TrustedTypePolicy -@JS() -@staticInterop -abstract class DomTrustedTypePolicy {} - -/// A subset of TrustedTypePolicy methods. -extension DomTrustedTypePolicyExtension on DomTrustedTypePolicy { +@JS('TrustedTypePolicy') +extension type DomTrustedTypePolicy._(JSObject _) implements JSObject { /// Creates a `TrustedScriptURL` for the given [input]. /// /// `input` is a string containing the data to be _sanitized_ by the policy. - @JS('createScriptURL') - external DomTrustedScriptURL _createScriptURL(JSString input); - DomTrustedScriptURL createScriptURL(String input) => _createScriptURL(input.toJS); + external DomTrustedScriptURL createScriptURL(String input); } /// Represents a string that a developer can insert into an _injection sink_ @@ -3339,16 +2206,12 @@ extension DomTrustedTypePolicyExtension on DomTrustedTypePolicy { /// constructor. /// /// See: https://developer.mozilla.org/en-US/docs/Web/API/TrustedScriptURL -@JS() -@staticInterop -abstract class DomTrustedScriptURL {} - -/// A subset of TrustedScriptURL methods. -extension DomTrustedScriptUrlExtension on DomTrustedScriptURL { +@JS('TrustedScriptURL') +extension type DomTrustedScriptURL._(JSObject _) implements JSObject { /// Exposes the `toString` JS method of TrustedScriptURL. @JS('toString') - external JSString _toString(); - String get url => _toString().toDart; + external String _toString(); + String get url => _toString(); } // The expected set of files that the flutter-engine TrustedType policy is going @@ -3358,12 +2221,12 @@ const Set _expectedFilesForTT = {'canvaskit.js'}; // The definition of the `flutter-engine` TrustedType policy. // Only accessible if the Trusted Types API is available. final DomTrustedTypePolicy _ttPolicy = domWindow.trustedTypes!.createPolicy( - 'flutter-engine'.toJS, + 'flutter-engine', DomTrustedTypePolicyOptions( // Validates the given [url]. createScriptURL: - (JSString url) { - final Uri uri = Uri.parse(url.toDart); + (String url) { + final Uri uri = Uri.parse(url); if (_expectedFilesForTT.contains(uri.pathSegments.last)) { return uri.toString().toJS; } @@ -3393,28 +2256,18 @@ JSAny createTrustedScriptUrl(String url) { DomMessageChannel createDomMessageChannel() => DomMessageChannel(); -bool domInstanceOfString(Object? element, String objectType) => - js_util.instanceOfString(element, objectType); +bool domInstanceOfString(JSAny element, String objectType) => element.instanceOfString(objectType); /// This is the shared interface for APIs that return either /// `NodeList` or `HTMLCollection`. Do *not* add any API to this class that /// isn't support by both JS objects. Furthermore, this is an internal class and /// should only be returned as a wrapped object to Dart. -@JS() -@staticInterop -class _DomList {} - -extension DomListExtension on _DomList { - @JS('length') - external JSNumber get _length; - double get length => _length.toDartDouble; - - @JS('item') - external DomNode _item(JSNumber index); - DomNode item(int index) => _item(index.toJS); +extension type _DomList._(JSObject _) implements JSObject { + external double get length; + external JSObject item(int index); } -class _DomListIterator implements Iterator { +class _DomListIterator implements Iterator { _DomListIterator(this.list); final _DomList list; @@ -3433,7 +2286,7 @@ class _DomListIterator implements Iterator { T get current => list.item(index) as T; } -class _DomListWrapper extends Iterable { +class _DomListWrapper extends Iterable { _DomListWrapper._(this.list); final _DomList list; @@ -3448,72 +2301,15 @@ class _DomListWrapper extends Iterable { /// This is a work around for a `TypeError` which can be triggered by calling /// `toList` on the `Iterable`. -Iterable createDomListWrapper(_DomList list) => _DomListWrapper._(list).cast(); +Iterable createDomListWrapper(_DomList list) => _DomListWrapper._(list); -// https://developer.mozilla.org/en-US/docs/Web/API/TouchList -@JS() -@staticInterop -class _DomTouchList {} - -extension DomTouchListExtension on _DomTouchList { - @JS('length') - external JSNumber get _length; - double get length => _length.toDartDouble; - - @JS('item') - external DomNode _item(JSNumber index); - DomNode item(int index) => _item(index.toJS); -} - -class _DomTouchListIterator implements Iterator { - _DomTouchListIterator(this.list); - - final _DomTouchList list; - int index = -1; - - @override - bool moveNext() { - index++; - if (index > list.length) { - throw StateError('Iterator out of bounds'); - } - return index < list.length; - } - - @override - T get current => list.item(index) as T; -} - -class _DomTouchListWrapper extends Iterable { - _DomTouchListWrapper._(this.list); - - final _DomTouchList list; - - @override - Iterator get iterator => _DomTouchListIterator(list); - - /// Override the length to avoid iterating through the whole collection. - @override - int get length => list.length.toInt(); -} - -Iterable createDomTouchListWrapper(_DomTouchList list) => - _DomTouchListWrapper._(list).cast(); - -@JS() -@staticInterop -class DomSymbol {} - -extension DomSymbolExtension on DomSymbol { - @JS('iterator') +@JS('Symbol') +extension type DomSymbol._(JSObject _) implements JSObject { external JSAny get iterator; } -@JS() -@staticInterop -class DomIntl {} - -extension DomIntlExtension on DomIntl { +@JS('Intl') +extension type DomIntl._(JSObject _) implements JSObject { // ignore: non_constant_identifier_names external JSAny? get Segmenter; @@ -3524,57 +2320,40 @@ extension DomIntlExtension on DomIntl { } @JS('Intl.Segmenter') -@staticInterop // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter -class DomSegmenter { +extension type DomSegmenter._(JSObject _) implements JSObject { // TODO(joshualitt): `locales` should really be typed as `JSAny?`, and we // should pass `JSUndefined`. Revisit this after we reify `JSUndefined` on // Dart2Wasm. - external factory DomSegmenter(JSArray locales, JSAny options); -} + external DomSegmenter(JSArray locales, JSAny options); -extension DomSegmenterExtension on DomSegmenter { @JS('segment') external DomSegments segmentRaw(JSString text); - DomSegments segment(String text) => segmentRaw(text.toJS); + external DomSegments segment(String text); } -@JS() -@staticInterop // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter/segment/Segments -class DomSegments {} - -extension DomSegmentsExtension on DomSegments { +@JS('Segments') +extension type DomSegments._(JSObject _) implements JSObject { DomIteratorWrapper iterator() { - final DomIterator segmentIterator = - js_util.callMethod(this, domSymbol.iterator, const []) as DomIterator; + final DomIterator segmentIterator = callMethod(domSymbol.iterator)! as DomIterator; return DomIteratorWrapper(segmentIterator); } } -@JS() -@staticInterop // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols -class DomIterator {} - -extension DomIteratorExtension on DomIterator { +@JS('Iterator') +extension type DomIterator._(JSObject _) implements JSObject { external DomIteratorResult next(); } -@JS() -@staticInterop -class DomIteratorResult {} - -extension DomIteratorResultExtension on DomIteratorResult { - @JS('done') - external JSBoolean get _done; - bool get done => _done.toDart; - +extension type DomIteratorResult._(JSObject _) implements JSObject { + external bool get done; external JSAny get value; } /// Wraps a native JS iterator to provide a Dart [Iterator]. -class DomIteratorWrapper implements Iterator { +class DomIteratorWrapper implements Iterator { DomIteratorWrapper(this._iterator); final DomIterator _iterator; @@ -3594,26 +2373,11 @@ class DomIteratorWrapper implements Iterator { } } -@JS() -@staticInterop -class DomSegment {} - -extension DomSegmentExtension on DomSegment { - @JS('index') - external JSNumber get _index; - int get index => _index.toDartDouble.toInt(); - - @JS('isWordLike') - external JSBoolean get _isWordLike; - bool get isWordLike => _isWordLike.toDart; - - @JS('segment') - external JSString get _segment; - String get segment => _segment.toDart; - - @JS('breakType') - external JSString get _breakType; - String get breakType => _breakType.toDart; +extension type DomSegment._(JSObject _) implements JSObject { + external int get index; + external bool get isWordLike; + external String get segment; + external String get breakType; } DomSegmenter createIntlSegmenter({required String granularity}) { @@ -3625,30 +2389,14 @@ DomSegmenter createIntlSegmenter({required String granularity}) { } @JS('Intl.v8BreakIterator') -@staticInterop -class DomV8BreakIterator { - external factory DomV8BreakIterator(JSArray locales, JSAny options); -} +extension type DomV8BreakIterator._(JSObject _) implements JSObject { + external DomV8BreakIterator(JSArray locales, JSAny options); -extension DomV8BreakIteratorExtension on DomV8BreakIterator { - @JS('adoptText') external void adoptText(JSString text); - - @JS('first') - external JSNumber _first(); - double first() => _first().toDartDouble; - - @JS('next') - external JSNumber _next(); - double next() => _next().toDartDouble; - - @JS('current') - external JSNumber _current(); - double current() => _current().toDartDouble; - - @JS('breakType') - external JSString _breakType(); - String breakType() => _breakType().toDart; + external double first(); + external double next(); + external double current(); + external String breakType(); } DomV8BreakIterator createV8BreakIterator() { @@ -3660,23 +2408,16 @@ DomV8BreakIterator createV8BreakIterator() { } @JS('TextDecoder') -@staticInterop -class DomTextDecoder { - external factory DomTextDecoder(); -} +extension type DomTextDecoder._(JSObject _) implements JSObject { + external DomTextDecoder(); -extension DomTextDecoderExtension on DomTextDecoder { external JSString decode(JSTypedArray buffer); } @JS('window.FinalizationRegistry') -@staticInterop -class DomFinalizationRegistry { - external factory DomFinalizationRegistry(JSFunction cleanup); -} +extension type DomFinalizationRegistry._(JSObject _) implements JSObject { + external DomFinalizationRegistry(JSFunction cleanup); -extension DomFinalizationRegistryExtension on DomFinalizationRegistry { - @JS('register') external void register(ExternalDartReference target, ExternalDartReference value); @JS('register') @@ -3686,7 +2427,6 @@ extension DomFinalizationRegistryExtension on DomFinalizationRegistry { ExternalDartReference token, ); - @JS('unregister') external void unregister(ExternalDartReference token); } diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/high_contrast.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/high_contrast.dart index cb9b0501777..1e2e51b6ed4 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/high_contrast.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/high_contrast.dart @@ -21,9 +21,7 @@ class HighContrastSupport { final DomMediaQueryList _highContrastMediaQuery = domWindow.matchMedia( _highContrastMediaQueryString, ); - late final DomEventListener _onHighContrastChangeListener = createDomEventListener( - _onHighContrastChange, - ); + late final DomEventListener _onHighContrastChangeListener = _onHighContrastChange.toJS; bool get isHighContrastEnabled => _highContrastMediaQuery.matches; @@ -43,7 +41,7 @@ class HighContrastSupport { } } - JSVoid _onHighContrastChange(DomEvent event) { + void _onHighContrastChange(DomEvent event) { final DomMediaQueryListEvent mqEvent = event as DomMediaQueryListEvent; final bool isHighContrastEnabled = mqEvent.matches!; for (final HighContrastListener listener in _listeners) { diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/image_decoder.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/image_decoder.dart index 5935943f233..c2b8f86cc51 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/image_decoder.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/image_decoder.dart @@ -102,18 +102,18 @@ abstract class BrowserImageDecoder implements ui.Codec { try { final ImageDecoder webDecoder = ImageDecoder( ImageDecoderOptions( - type: contentType.toJS, + type: contentType, data: dataSource, // Flutter always uses premultiplied alpha when decoding. - premultiplyAlpha: 'premultiply'.toJS, + premultiplyAlpha: 'premultiply', // "default" gives the browser the liberty to convert to display-appropriate // color space, typically SRGB, which is what we want. - colorSpaceConversion: 'default'.toJS, + colorSpaceConversion: 'default', // 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.toJS, + preferAnimation: true, ), ); @@ -121,8 +121,6 @@ abstract class BrowserImageDecoder implements ui.Codec { // Flutter doesn't have an API for progressive loading of images, so we // wait until the image is fully decoded. - // package:js bindings don't work with getters that return a Promise, which - // is why js_util is used instead. await promiseToFuture(getJsProperty(webDecoder, 'completed')); frameCount = webDecoder.tracks.selectedTrack!.frameCount.toInt(); @@ -151,7 +149,11 @@ abstract class BrowserImageDecoder implements ui.Codec { return webDecoder; } catch (error) { - if (domInstanceOfString(error, 'DOMException')) { + // TODO(srujzs): Replace this with `error.isJSAny` when we have that API + // in `dart:js_interop`. + // https://github.com/dart-lang/sdk/issues/56905 + // ignore: invalid_runtime_check_with_js_interop_types + if (error is JSAny && error.isA()) { if ((error as DomException).name == DomException.notSupported) { throw ImageCodecException( "Image file format ($contentType) is not supported by this browser's ImageDecoder API.\n" @@ -172,7 +174,7 @@ abstract class BrowserImageDecoder implements ui.Codec { _debugCheckNotDisposed(); final ImageDecoder webDecoder = await _getOrCreateWebDecoder(); final DecodeResult result = await promiseToFuture( - webDecoder.decode(DecodeOptions(frameIndex: _nextFrameIndex.toJS)), + webDecoder.decode(DecodeOptions(frameIndex: _nextFrameIndex)), ); final VideoFrame frame = result.image; _nextFrameIndex = (_nextFrameIndex + 1) % frameCount; diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/js_interop/js_app.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/js_interop/js_app.dart index 42be1959028..812a78c3360 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/js_interop/js_app.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/js_interop/js_app.dart @@ -2,22 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -@JS() -library js_app; - import 'dart:js_interop'; import 'package:ui/src/engine.dart'; /// The JS bindings for the configuration object passed to [FlutterApp.addView]. -@JS() -@anonymous -@staticInterop -class JsFlutterViewOptions { - external factory JsFlutterViewOptions(); -} +extension type JsFlutterViewOptions._(JSObject _) implements JSObject { + factory JsFlutterViewOptions() => JSObject() as JsFlutterViewOptions; -/// The attributes of the [JsFlutterViewOptions] object. -extension JsFlutterViewOptionsExtension on JsFlutterViewOptions { @JS('hostElement') external DomElement? get _hostElement; DomElement get hostElement { @@ -25,32 +16,21 @@ extension JsFlutterViewOptionsExtension on JsFlutterViewOptions { return _hostElement!; } - @JS('viewConstraints') - external JsViewConstraints? get _viewConstraints; - JsViewConstraints? get viewConstraints { - return _viewConstraints; - } - + external JsViewConstraints? get viewConstraints; external JSAny? get initialData; } /// The JS bindings for a [ViewConstraints] object. -@JS() -@anonymous -@staticInterop -class JsViewConstraints { +/// +/// Attributes are expressed in *logical* pixels. +extension type JsViewConstraints._(JSObject _) implements JSObject { external factory JsViewConstraints({ double? minWidth, double? maxWidth, double? minHeight, double? maxHeight, }); -} -/// The attributes of a [JsViewConstraints] object. -/// -/// These attributes are expressed in *logical* pixels. -extension JsViewConstraintsExtension on JsViewConstraints { external double? get maxHeight; external double? get maxWidth; external double? get minHeight; @@ -58,17 +38,11 @@ extension JsViewConstraintsExtension on JsViewConstraints { } /// The public JS API of a running Flutter Web App. -@JS() -@anonymous -@staticInterop -abstract class FlutterApp { +extension type FlutterApp._primary(JSObject _) implements JSObject { factory FlutterApp({ required AddFlutterViewFn addView, required RemoveFlutterViewFn removeView, - }) => FlutterApp._( - addView: addView.toJS, - removeView: ((JSNumber id) => removeView(id.toDartInt)).toJS, - ); + }) => FlutterApp._(addView: addView.toJS, removeView: ((int id) => removeView(id)).toJS); external factory FlutterApp._({required JSFunction addView, required JSFunction removeView}); } diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/js_interop/js_loader.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/js_interop/js_loader.dart index 43b40d388e6..89d6610602b 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/js_interop/js_loader.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/js_interop/js_loader.dart @@ -10,11 +10,7 @@ import 'dart:js_interop_unsafe'; import 'package:ui/src/engine.dart'; -@JS() -@staticInterop -class FlutterJS {} - -extension FlutterJSExtension on FlutterJS { +extension type FlutterJS._(JSObject _) implements JSObject { external FlutterLoader? get loader; } @@ -23,13 +19,9 @@ extension FlutterJSExtension on FlutterJS { @JS('_flutter') external FlutterJS? get flutter; -@JS() -@staticInterop -class FlutterLoader {} - -extension FlutterLoaderExtension on FlutterLoader { +extension type FlutterLoader._(JSObject _) implements JSObject { external void didCreateEngineInitializer(FlutterEngineInitializer initializer); - bool get isAutoStart => !(this as JSObject).has('didCreateEngineInitializer'); + bool get isAutoStart => !has('didCreateEngineInitializer'); } /// Typedef for the function that initializes the flutter engine. @@ -49,10 +41,7 @@ typedef ImmediateRunAppFn = Future Function(); /// /// As a convenience method, [autoStart] allows the user to immediately initialize /// and run a Flutter Web app, from JavaScript. -@JS() -@anonymous -@staticInterop -abstract class FlutterEngineInitializer { +extension type FlutterEngineInitializer._primary(JSObject _) implements JSObject { factory FlutterEngineInitializer({ required InitializeEngineFn initializeEngine, required ImmediateRunAppFn autoStart, @@ -73,13 +62,9 @@ abstract class FlutterEngineInitializer { /// A class that exposes a function that runs the Flutter app, /// and returns a promise of a FlutterAppCleaner. -@JS() -@anonymous -@staticInterop -abstract class FlutterAppRunner { - factory FlutterAppRunner({required RunAppFn runApp}) => FlutterAppRunner._( - runApp: (([RunAppFnParameters? args]) => (runApp(args) as Future).toPromise).toJS, - ); +extension type FlutterAppRunner._primary(JSObject _) implements JSObject { + factory FlutterAppRunner({required RunAppFn runApp}) => + FlutterAppRunner._(runApp: (([RunAppFnParameters? args]) => runApp(args).toPromise).toJS); /// Runs a flutter app external factory FlutterAppRunner._({ @@ -89,10 +74,7 @@ abstract class FlutterAppRunner { /// The shape of the object that can be passed as parameter to the /// runApp function of the FlutterAppRunner object (from JS). -@JS() -@anonymous -@staticInterop -abstract class RunAppFnParameters {} +extension type RunAppFnParameters._(JSObject _) implements JSObject {} /// Typedef for the function that runs the flutter app main entrypoint. typedef RunAppFn = Future Function([RunAppFnParameters?]); diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/js_interop/js_typed_data.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/js_interop/js_typed_data.dart index f1150dfb382..b58cb95a756 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/js_interop/js_typed_data.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/js_interop/js_typed_data.dart @@ -6,25 +6,7 @@ import 'dart:js_interop'; // Some APIs we need on typed arrays that are not exposed by the dart sdk yet extension TypedArrayExtension on JSTypedArray { - external JSTypedArray slice(JSNumber start, JSNumber end); - external void set(JSTypedArray source, JSNumber start); - external JSNumber get length; + external JSTypedArray slice(int start, int end); + external void set(JSTypedArray source, int start); + external int get length; } - -// These are constructors on `Uint8Array` that we need that aren't exposed in -// the dart sdk yet -@JS('Uint8Array') -@staticInterop -class JSUint8Array1 { - external factory JSUint8Array1._create1(JSAny bufferOrLength); - external factory JSUint8Array1._create3(JSArrayBuffer buffer, JSNumber start, JSNumber length); -} - -JSUint8Array createUint8ArrayFromBuffer(JSArrayBuffer buffer) => - JSUint8Array1._create1(buffer) as JSUint8Array; - -JSUint8Array createUint8ArrayFromSubBuffer(JSArrayBuffer buffer, int start, int length) => - JSUint8Array1._create3(buffer, start.toJS, length.toJS) as JSUint8Array; - -JSUint8Array createUint8ArrayFromLength(int length) => - JSUint8Array1._create1(length.toJS) as JSUint8Array; diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/keyboard_binding.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/keyboard_binding.dart index 8e4ffc1e496..60ff035c950 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/keyboard_binding.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/keyboard_binding.dart @@ -142,7 +142,7 @@ class KeyboardBinding { final Map _listeners = {}; void _addEventListener(String eventName, DartDomEventListener handler) { - JSVoid loggedHandler(DomEvent event) { + void loggedHandler(DomEvent event) { if (_debugLogKeyEvents) { print(event.type); } @@ -151,16 +151,16 @@ class KeyboardBinding { } } - final DomEventListener wrappedHandler = createDomEventListener(loggedHandler); + final DomEventListener wrappedHandler = loggedHandler.toJS; assert(!_listeners.containsKey(eventName)); _listeners[eventName] = wrappedHandler; - domWindow.addEventListener(eventName, wrappedHandler, true); + domWindow.addEventListener(eventName, wrappedHandler, true.toJS); } /// Remove all active event listeners. void _clearListeners() { _listeners.forEach((String eventName, DomEventListener listener) { - domWindow.removeEventListener(eventName, listener, true); + domWindow.removeEventListener(eventName, listener, true.toJS); }); _listeners.clear(); } diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/platform_dispatcher.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/platform_dispatcher.dart index 528b57bf8db..5bf16d1ec8c 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/platform_dispatcher.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/platform_dispatcher.dart @@ -830,11 +830,15 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher { return; } updateLocales(); // First time, for good measure. - _onLocaleChangedSubscription = DomSubscription(domWindow, 'languagechange', (DomEvent _) { - // Update internal config, then propagate the changes. - updateLocales(); - invokeOnLocaleChanged(); - }); + _onLocaleChangedSubscription = DomSubscription( + domWindow, + 'languagechange', + createDomEventListener((DomEvent _) { + // Update internal config, then propagate the changes. + updateLocales(); + invokeOnLocaleChanged(); + }), + ); } /// Removes the [_onLocaleChangedSubscription]. @@ -1079,10 +1083,11 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher { _brightnessMediaQuery.matches ? ui.Brightness.dark : ui.Brightness.light, ); - _brightnessMediaQueryListener = createDomEventListener((DomEvent event) { - final DomMediaQueryListEvent mqEvent = event as DomMediaQueryListEvent; - _updatePlatformBrightness(mqEvent.matches! ? ui.Brightness.dark : ui.Brightness.light); - }); + _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/engine/src/flutter/lib/web_ui/lib/src/engine/platform_dispatcher/view_focus_binding.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/platform_dispatcher/view_focus_binding.dart index 64a1ca6adee..a7d73c19296 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/platform_dispatcher/view_focus_binding.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/platform_dispatcher/view_focus_binding.dart @@ -3,6 +3,8 @@ // found in the LICENSE file. import 'dart:async'; +import 'dart:js_interop'; + import 'package:meta/meta.dart'; import 'package:ui/src/engine.dart'; import 'package:ui/ui.dart' as ui; @@ -85,7 +87,7 @@ final class ViewFocusBinding { // The right event type needs to be checked because Chrome seems to be firing // `Event` events instead of `KeyboardEvent` events when autofilling is used. // See https://github.com/flutter/flutter/issues/149968 for more info. - if (event is DomKeyboardEvent && (event.shiftKey ?? false)) { + if (event.isA() && ((event as DomKeyboardEvent).shiftKey ?? false)) { _viewFocusDirection = ui.ViewFocusDirection.backward; } }); diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/pointer_binding.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/pointer_binding.dart index d25f54a78e7..da6e7712d9c 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/pointer_binding.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/pointer_binding.dart @@ -91,7 +91,7 @@ class SafariPointerEventWorkaround { void workAroundMissingPointerEvents() { // We only need to attach the listener once. if (_listener == null) { - _listener = createDomEventListener((_) {}); + _listener = createDomEventListener((DomEvent _) {}); domDocument.addEventListener('touchstart', _listener); } } @@ -322,9 +322,9 @@ class ClickDebouncer { assert(event.type == 'pointerdown', 'Click debouncing must begin with a pointerdown'); final DomEventTarget? target = event.target; - if (target is DomElement && target.hasAttribute('flt-tappable')) { + if (target.isA() && (target! as DomElement).hasAttribute('flt-tappable')) { _state = ( - target: target, + target: target as DomElement, // The 200ms duration was chosen empirically by testing tapping, mouse // clicking, trackpad tapping and clicking, as well as the following // screen readers: TalkBack on Android, VoiceOver on macOS, Narrator/ @@ -471,7 +471,7 @@ class Listener { target.addEventListener(event, jsHandler); } else { final Map eventOptions = {'passive': passive}; - target.addEventListenerWithOptions(event, jsHandler, eventOptions); + target.addEventListener(event, jsHandler, eventOptions.toJSAnyDeep); } final Listener listener = Listener._(event: event, target: target, handler: jsHandler); @@ -528,9 +528,9 @@ abstract class _BaseAdapter { /// instead, because the browser doesn't fire the latter two for DOM elements /// when the pointer is outside the window. void addEventListener(DomEventTarget target, String eventName, DartDomEventListener handler) { - JSVoid loggedHandler(DomEvent event) { + void loggedHandler(DomEvent event) { if (_debugLogPointerEvents) { - if (domInstanceOfString(event, 'PointerEvent')) { + if (event.isA()) { final DomPointerEvent pointerEvent = event as DomPointerEvent; final ui.Offset offset = computeEventOffsetToTarget(event, _view); print( @@ -730,7 +730,7 @@ mixin _WheelEventListenerMixin on _BaseAdapter { return; } - assert(domInstanceOfString(event, 'WheelEvent')); + assert(event.isA()); if (_debugLogPointerEvents) { print(event.type); } diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/raw_keyboard.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/raw_keyboard.dart index 6c47f42b772..7a94e29ca92 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/raw_keyboard.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/raw_keyboard.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'dart:async'; +import 'dart:js_interop'; import 'dart:typed_data'; import 'package:ui/ui_web/src/ui_web.dart' as ui_web; @@ -83,7 +84,7 @@ class RawKeyboard { } void handleHtmlEvent(DomEvent domEvent) { - if (!domInstanceOfString(domEvent, 'KeyboardEvent')) { + if (!domEvent.isA()) { return; } diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/safe_browser_api.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/safe_browser_api.dart index 87a51d03f72..bea9ba1e698 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/safe_browser_api.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/safe_browser_api.dart @@ -131,8 +131,8 @@ void vibrate(int durationMs) { /// The [DomCanvasElement] factory assumes that element allocation will /// succeed and will return a non-null element. This is not always true. For /// example, when Safari on iOS runs out of memory it returns null. -DomCanvasElement? tryCreateCanvasElement(int width, int height) { - final DomCanvasElement? canvas = js_util.callMethod( +DomHTMLCanvasElement? tryCreateCanvasElement(int width, int height) { + final DomHTMLCanvasElement? canvas = js_util.callMethod( domDocument, 'createElement', ['CANVAS'], @@ -198,20 +198,13 @@ bool get _isBrowserImageDecoderStable => ui_web.browser.browserEngine == ui_web. /// /// * https://www.w3.org/TR/webcodecs/#imagedecoder-interface @JS('window.ImageDecoder') -@staticInterop -class ImageDecoder { - external factory ImageDecoder(ImageDecoderOptions options); -} +extension type ImageDecoder._(JSObject _) implements JSObject { + external ImageDecoder(ImageDecoderOptions options); -extension ImageDecoderExtension on ImageDecoder { external ImageTrackList get tracks; - - @JS('complete') - external JSBoolean get _complete; - bool get complete => _complete.toDart; - + external bool get complete; external JSPromise decode(DecodeOptions options); - external JSVoid close(); + external void close(); } /// Options passed to the `ImageDecoder` constructor. @@ -219,18 +212,15 @@ extension ImageDecoderExtension on ImageDecoder { /// See also: /// /// * https://www.w3.org/TR/webcodecs/#imagedecoderinit-interface -@JS() -@anonymous -@staticInterop -class ImageDecoderOptions { - external factory ImageDecoderOptions({ - required JSString type, +extension type ImageDecoderOptions._(JSObject _) implements JSObject { + external ImageDecoderOptions({ + required String type, required JSAny data, - required JSString premultiplyAlpha, - JSNumber? desiredWidth, - JSNumber? desiredHeight, - required JSString colorSpaceConversion, - required JSBoolean preferAnimation, + required String premultiplyAlpha, + double? desiredWidth, + double? desiredHeight, + required String colorSpaceConversion, + required bool preferAnimation, }); } @@ -239,17 +229,9 @@ class ImageDecoderOptions { /// See also: /// /// * https://www.w3.org/TR/webcodecs/#imagedecoderesult-interface -@JS() -@anonymous -@staticInterop -class DecodeResult {} - -extension DecodeResultExtension on DecodeResult { +extension type DecodeResult(JSObject _) implements JSObject { external VideoFrame get image; - - @JS('complete') - external JSBoolean get _complete; - bool get complete => _complete.toDart; + external bool get complete; } /// Options passed to [ImageDecoder.decode]. @@ -257,11 +239,8 @@ extension DecodeResultExtension on DecodeResult { /// See also: /// /// * https://www.w3.org/TR/webcodecs/#dictdef-imagedecodeoptions -@JS() -@anonymous -@staticInterop -class DecodeOptions { - external factory DecodeOptions({required JSNumber frameIndex}); +extension type DecodeOptions._(JSObject _) implements JSObject { + external DecodeOptions({required int frameIndex}); } /// The only frame in a static image, or one of the frames in an animated one. @@ -271,46 +250,21 @@ class DecodeOptions { /// See also: /// /// * https://www.w3.org/TR/webcodecs/#videoframe-interface -@JS() -@anonymous -@staticInterop -class VideoFrame implements DomCanvasImageSource {} - -extension VideoFrameExtension on VideoFrame { - @JS('allocationSize') - external JSNumber _allocationSize(); - double allocationSize() => _allocationSize().toDartDouble; +extension type VideoFrame(JSObject _) implements JSObject, DomCanvasImageSource { + external double allocationSize(); @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.toDartDouble; - - @JS('codedHeight') - external JSNumber get _codedHeight; - double get codedHeight => _codedHeight.toDartDouble; - - @JS('displayWidth') - external JSNumber get _displayWidth; - double get displayWidth => _displayWidth.toDartDouble; - - @JS('displayHeight') - external JSNumber get _displayHeight; - double get displayHeight => _displayHeight.toDartDouble; - - @JS('duration') - external JSNumber? get _duration; - double? get duration => _duration?.toDartDouble; - + external String? get format; + external double get codedWidth; + external double get codedHeight; + external double get displayWidth; + external double get displayHeight; + external double? get duration; external VideoFrame clone(); - external JSVoid close(); + external void close(); } /// Corresponds to the browser's `ImageTrackList` type. @@ -318,12 +272,7 @@ extension VideoFrameExtension on VideoFrame { /// See also: /// /// * https://www.w3.org/TR/webcodecs/#imagetracklist-interface -@JS() -@anonymous -@staticInterop -class ImageTrackList {} - -extension ImageTrackListExtension on ImageTrackList { +extension type ImageTrackList(JSObject _) implements JSObject { external JSPromise get ready; external ImageTrack? get selectedTrack; } @@ -333,19 +282,9 @@ extension ImageTrackListExtension on ImageTrackList { /// See also: /// /// * https://www.w3.org/TR/webcodecs/#imagetrack -@JS() -@anonymous -@staticInterop -class ImageTrack {} - -extension ImageTrackExtension on ImageTrack { - @JS('repetitionCount') - external JSNumber get _repetitionCount; - double get repetitionCount => _repetitionCount.toDartDouble; - - @JS('frameCount') - external JSNumber get _frameCount; - double get frameCount => _frameCount.toDartDouble; +extension type ImageTrack(JSObject _) implements JSObject { + external double get repetitionCount; + external double get frameCount; } void scaleCanvas2D(Object context2d, num x, num y) { @@ -399,7 +338,7 @@ class GlContext { _canvas = canvas; } - GlContext._fromCanvasElement(DomCanvasElement canvas, bool useWebGl1) + GlContext._fromCanvasElement(DomHTMLCanvasElement canvas, bool useWebGl1) : glContext = canvas.getContext(useWebGl1 ? 'webgl' : 'webgl2', { 'premultipliedAlpha': false, @@ -844,7 +783,7 @@ class GlContext { ); return imageBitmap; } else { - final DomCanvasElement canvas = createDomCanvasElement( + final DomHTMLCanvasElement canvas = createDomCanvasElement( width: _widthInPixels, height: _heightInPixels, ); @@ -856,7 +795,7 @@ class GlContext { /// Returns image data in data url format. String toImageUrl() { - final DomCanvasElement canvas = createDomCanvasElement( + final DomHTMLCanvasElement canvas = createDomCanvasElement( width: _widthInPixels, height: _heightInPixels, ); @@ -970,12 +909,12 @@ class OffScreenCanvas { } DomOffscreenCanvas? offScreenCanvas; - DomCanvasElement? canvasElement; + DomHTMLCanvasElement? canvasElement; int width; int height; static bool? _supported; - void _updateCanvasCssSize(DomCanvasElement element) { + void _updateCanvasCssSize(DomHTMLCanvasElement element) { final double cssWidth = width / EngineFlutterDisplay.instance.browserDevicePixelRatio; final double cssHeight = height / EngineFlutterDisplay.instance.browserDevicePixelRatio; element.style @@ -1012,11 +951,11 @@ class OffScreenCanvas { : canvasElement!.getContext('2d'); } - DomCanvasRenderingContextBitmapRenderer? getBitmapRendererContext() { + DomImageBitmapRenderingContext? getBitmapRendererContext() { return (offScreenCanvas != null ? offScreenCanvas!.getContext('bitmaprenderer') : canvasElement!.getContext('bitmaprenderer')) - as DomCanvasRenderingContextBitmapRenderer?; + as DomImageBitmapRenderingContext?; } /// Feature detection for transferToImageBitmap on OffscreenCanvas. diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/scene_view.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/scene_view.dart index 6f9b71bc923..69e030adb3f 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/scene_view.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/scene_view.dart @@ -240,7 +240,7 @@ sealed class SliceContainer { final class PictureSliceContainer extends SliceContainer { factory PictureSliceContainer(ui.Rect bounds) { final DomElement container = domDocument.createElement(kCanvasContainerTag); - final DomCanvasElement canvas = createDomCanvasElement( + final DomHTMLCanvasElement canvas = createDomCanvasElement( width: bounds.width.toInt(), height: bounds.height.toInt(), ); @@ -289,13 +289,13 @@ final class PictureSliceContainer extends SliceContainer { } void renderBitmap(DomImageBitmap bitmap) { - final DomCanvasRenderingContextBitmapRenderer ctx = canvas.contextBitmapRenderer; + final DomImageBitmapRenderingContext ctx = canvas.contextBitmapRenderer; ctx.transferFromImageBitmap(bitmap); } @override final DomElement container; - final DomCanvasElement canvas; + final DomHTMLCanvasElement canvas; } final class PlatformViewContainer extends SliceContainer { diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/focusable.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/focusable.dart index 79b7925bb8f..b60a8f03438 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/focusable.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/focusable.dart @@ -168,8 +168,12 @@ class AccessibilityFocusManager { final _FocusTarget newTarget = ( semanticsNodeId: semanticsNodeId, element: element, - domFocusListener: createDomEventListener((_) => _didReceiveDomFocus()), - domBlurListener: createDomEventListener((_) => _didReceiveDomBlur()), + domFocusListener: createDomEventListener((DomEvent _) { + _didReceiveDomFocus(); + }), + domBlurListener: createDomEventListener((DomEvent _) { + _didReceiveDomBlur(); + }), ); _target = newTarget; _lastEvent = AccessibilityFocusManagerEvent.nothing; diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/incrementable.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/incrementable.dart index e90954ee70c..cecff590d55 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/incrementable.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/incrementable.dart @@ -36,7 +36,7 @@ class SemanticIncrementable extends SemanticRole { _element.addEventListener( 'change', - createDomEventListener((_) { + createDomEventListener((DomEvent _) { if (_element.disabled!) { return; } diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/route.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/route.dart index 30de3de023f..40d7e3f7ee5 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/route.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/route.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import '../dom.dart'; import '../semantics.dart'; import '../util.dart'; diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/scrollable.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/scrollable.dart index a281ae48812..c5fb4cf2025 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/scrollable.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/scrollable.dart @@ -163,7 +163,7 @@ class SemanticScrollable extends SemanticRole { }; EngineSemantics.instance.addGestureModeListener(_gestureModeListener!); - scrollListener = createDomEventListener((_) { + scrollListener = createDomEventListener((DomEvent _) { if (!_canScroll) { return; } diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/semantics.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/semantics.dart index a9459d640aa..fd14c1ee600 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/semantics.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/semantics.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 'dart:math' as math; import 'dart:typed_data'; @@ -615,11 +616,21 @@ abstract class SemanticRole { void removeAttribute(String name) => element.removeAttribute(name); - void addEventListener(String type, DomEventListener? listener, [bool? useCapture]) => - element.addEventListener(type, listener, useCapture); + void addEventListener(String type, DomEventListener? listener, [bool? useCapture]) { + if (useCapture != null) { + element.addEventListener(type, listener, useCapture.toJS); + } else { + element.addEventListener(type, listener); + } + } - void removeEventListener(String type, DomEventListener? listener, [bool? useCapture]) => - element.removeEventListener(type, listener, useCapture); + void removeEventListener(String type, DomEventListener? listener, [bool? useCapture]) { + if (useCapture != null) { + element.removeEventListener(type, listener, useCapture.toJS); + } else { + element.removeEventListener(type, listener); + } + } /// Convenience getter for the [Focusable] behavior, if any. Focusable? get focusable => _focusable; diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/semantics_helper.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/semantics_helper.dart index ccf8c41151e..b9a448d054f 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/semantics_helper.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/semantics_helper.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'dart:async'; +import 'dart:js_interop'; import 'package:meta/meta.dart'; import 'package:ui/ui_web/src/ui_web.dart' as ui_web; @@ -184,7 +185,7 @@ class DesktopSemanticsEnabler extends SemanticsEnabler { createDomEventListener((DomEvent event) { tryEnableSemantics(event); }), - true, + true.toJS, ); // Adding roles to semantics placeholder. 'aria-live' will make sure that @@ -382,7 +383,7 @@ class MobileSemanticsEnabler extends SemanticsEnabler { createDomEventListener((DomEvent event) { tryEnableSemantics(event); }), - true, + true.toJS, ); placeholder diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/text_field.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/text_field.dart index 815bcf7447d..8aedd26231a 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/text_field.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/semantics/text_field.dart @@ -126,9 +126,15 @@ class SemanticsTextEditingStrategy extends DefaultTextEditingStrategy { } // Subscribe to text and selection changes. - subscriptions.add(DomSubscription(activeDomElement, 'input', handleChange)); - subscriptions.add(DomSubscription(activeDomElement, 'keydown', maybeSendAction)); - subscriptions.add(DomSubscription(domDocument, 'selectionchange', handleChange)); + subscriptions.add( + DomSubscription(activeDomElement, 'input', createDomEventListener(handleChange)), + ); + subscriptions.add( + DomSubscription(activeDomElement, 'keydown', createDomEventListener(maybeSendAction)), + ); + subscriptions.add( + DomSubscription(domDocument, 'selectionchange', createDomEventListener(handleChange)), + ); preventDefaultForMouseEvents(); } diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/codecs.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/codecs.dart index 3cf1eeb83c7..0ce497165d4 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/codecs.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/codecs.dart @@ -2,8 +2,6 @@ // 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:ui/src/engine.dart'; import 'package:ui/src/engine/skwasm/skwasm_impl.dart'; import 'package:ui/ui.dart' as ui; @@ -20,8 +18,6 @@ class SkwasmImageDecoder extends BrowserImageDecoder { final int width = frame.displayWidth.toInt(); final int height = frame.displayHeight.toInt(); final SkwasmSurface surface = (renderer as SkwasmRenderer).surface; - return SkwasmImage( - imageCreateFromTextureSource(frame as JSObject, width, height, surface.handle), - ); + return SkwasmImage(imageCreateFromTextureSource(frame, width, height, surface.handle)); } } diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/filters.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/filters.dart index 74415a6e0d5..8d7679d9271 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/filters.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/filters.dart @@ -369,5 +369,7 @@ class SkwasmMaskFilter extends SkwasmObjectWrapper { ); static final SkwasmFinalizationRegistry _registry = - SkwasmFinalizationRegistry(maskFilterDispose); + SkwasmFinalizationRegistry( + (MaskFilterHandle handle) => maskFilterDispose(handle), + ); } diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/font_collection.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/font_collection.dart index 4ae92a36338..764f4cb98d6 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/font_collection.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/font_collection.dart @@ -23,7 +23,7 @@ class SkwasmTypeface extends SkwasmObjectWrapper { SkwasmTypeface(SkDataHandle data) : super(typefaceCreate(data), _registry); static final SkwasmFinalizationRegistry _registry = - SkwasmFinalizationRegistry(typefaceDispose); + SkwasmFinalizationRegistry((TypefaceHandle handle) => typefaceDispose(handle)); } class SkwasmFontCollection implements FlutterFontCollection { @@ -108,15 +108,15 @@ class SkwasmFontCollection implements FlutterFontCollection { int length = 0; final List chunks = []; await response.read((JSUint8Array chunk) { - length += chunk.length.toDartInt; + length += chunk.length; chunks.add(chunk); }); final SkDataHandle fontData = skDataCreate(length); int dataAddress = skDataGetPointer(fontData).cast().address; - final JSUint8Array wasmMemory = createUint8ArrayFromBuffer(skwasmInstance.wasmMemory.buffer); + final JSUint8Array wasmMemory = JSUint8Array(skwasmInstance.wasmMemory.buffer); for (final JSUint8Array chunk in chunks) { - wasmMemory.set(chunk, dataAddress.toJS); - dataAddress += chunk.length.toDartInt; + wasmMemory.set(chunk, dataAddress); + dataAddress += chunk.length; } final SkwasmTypeface typeface = SkwasmTypeface(fontData); skDataDispose(fontData); @@ -136,15 +136,15 @@ class SkwasmFontCollection implements FlutterFontCollection { int length = 0; final List chunks = []; await response.read((JSUint8Array chunk) { - length += chunk.length.toDartInt; + length += chunk.length; chunks.add(chunk); }); final SkDataHandle fontData = skDataCreate(length); int dataAddress = skDataGetPointer(fontData).cast().address; - final JSUint8Array wasmMemory = createUint8ArrayFromBuffer(skwasmInstance.wasmMemory.buffer); + final JSUint8Array wasmMemory = JSUint8Array(skwasmInstance.wasmMemory.buffer); for (final JSUint8Array chunk in chunks) { - wasmMemory.set(chunk, dataAddress.toJS); - dataAddress += chunk.length.toDartInt; + wasmMemory.set(chunk, dataAddress); + dataAddress += chunk.length; } final SkwasmTypeface typeface = SkwasmTypeface(fontData); diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/image.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/image.dart index 66938ce0876..2fe554c0779 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/image.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/image.dart @@ -39,7 +39,7 @@ class SkwasmImage extends SkwasmObjectWrapper implements ui.Image { } static final SkwasmFinalizationRegistry _registry = - SkwasmFinalizationRegistry(imageDispose); + SkwasmFinalizationRegistry((ImageHandle handle) => imageDispose(handle)); @override void dispose() { @@ -64,11 +64,11 @@ class SkwasmImage extends SkwasmObjectWrapper implements ui.Image { recorder.endRecording() as SkwasmPicture, ])).imageBitmaps.single; final DomOffscreenCanvas offscreenCanvas = createDomOffscreenCanvas( - bitmap.width.toDartInt, - bitmap.height.toDartInt, + bitmap.width, + bitmap.height, ); - final DomCanvasRenderingContextBitmapRenderer context = - offscreenCanvas.getContext('bitmaprenderer')! as DomCanvasRenderingContextBitmapRenderer; + final DomImageBitmapRenderingContext context = + offscreenCanvas.getContext('bitmaprenderer')! as DomImageBitmapRenderingContext; context.transferFromImageBitmap(bitmap); final DomBlob blob = await offscreenCanvas.convertToBlob(); final JSArrayBuffer arrayBuffer = (await blob.arrayBuffer().toDart)! as JSArrayBuffer; diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/paragraph.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/paragraph.dart index ef62bba7f0f..a9df744d8e7 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/paragraph.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/paragraph.dart @@ -51,7 +51,9 @@ class SkwasmLineMetrics extends SkwasmObjectWrapper implements u SkwasmLineMetrics._(LineMetricsHandle handle) : super(handle, _registry); static final SkwasmFinalizationRegistry _registry = - SkwasmFinalizationRegistry(lineMetricsDispose); + SkwasmFinalizationRegistry( + (LineMetricsHandle handle) => lineMetricsDispose(handle), + ); @override bool get hardBreak => lineMetricsGetHardBreak(handle); @@ -88,7 +90,9 @@ class SkwasmParagraph extends SkwasmObjectWrapper implements ui.Pa SkwasmParagraph(ParagraphHandle handle) : super(handle, _registry); static final SkwasmFinalizationRegistry _registry = - SkwasmFinalizationRegistry(paragraphDispose); + SkwasmFinalizationRegistry( + (ParagraphHandle handle) => paragraphDispose(handle), + ); bool _hasCheckedForMissingCodePoints = false; @@ -301,7 +305,9 @@ class SkwasmNativeTextStyle extends SkwasmObjectWrapper { factory SkwasmNativeTextStyle.defaultTextStyle() => SkwasmNativeTextStyle(textStyleCreate()); static final SkwasmFinalizationRegistry _registry = - SkwasmFinalizationRegistry(textStyleDispose); + SkwasmFinalizationRegistry( + (TextStyleHandle handle) => textStyleDispose(handle), + ); SkwasmNativeTextStyle copy() { return SkwasmNativeTextStyle(textStyleCopy(handle)); @@ -644,7 +650,9 @@ final class SkwasmStrutStyle extends SkwasmObjectWrapper implemen ) : super(handle, _registry); static final SkwasmFinalizationRegistry _registry = - SkwasmFinalizationRegistry(strutStyleDispose); + SkwasmFinalizationRegistry( + (StrutStyleHandle handle) => strutStyleDispose(handle), + ); final String? _fontFamily; final List? _fontFamilyFallback; @@ -835,7 +843,9 @@ class SkwasmParagraphStyle extends SkwasmObjectWrapper ) : super(handle, _registry); static final SkwasmFinalizationRegistry _registry = - SkwasmFinalizationRegistry(paragraphStyleDispose); + SkwasmFinalizationRegistry( + (ParagraphStyleHandle handle) => paragraphStyleDispose(handle), + ); final SkwasmNativeTextStyle textStyle; final String? defaultFontFamily; @@ -929,7 +939,9 @@ class SkwasmParagraphBuilder extends SkwasmObjectWrapper SkwasmParagraphBuilder._(ParagraphBuilderHandle handle, this.style) : super(handle, _registry); static final SkwasmFinalizationRegistry _registry = - SkwasmFinalizationRegistry(paragraphBuilderDispose); + SkwasmFinalizationRegistry( + (ParagraphBuilderHandle handle) => paragraphBuilderDispose(handle), + ); final SkwasmParagraphStyle style; final List textStyleStack = []; @@ -994,9 +1006,9 @@ class SkwasmParagraphBuilder extends SkwasmObjectWrapper // than a slice, but the TextDecoder API doesn't work on shared buffer // sources yet. // See https://bugs.chromium.org/p/chromium/issues/detail?id=1012656 - createUint8ArrayFromBuffer( + JSUint8Array( skwasmInstance.wasmMemory.buffer, - ).slice(utf8Data.address.toJS, (utf8Data.address + outSize.value).toJS), + ).slice(utf8Data.address, utf8Data.address + outSize.value), ); } diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/path.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/path.dart index 3710a9b2ee6..f327ac12e3f 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/path.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/path.dart @@ -26,7 +26,7 @@ class SkwasmPath extends SkwasmObjectWrapper implements ScenePath { SkwasmPath.fromHandle(PathHandle handle) : super(handle, _registry); static final SkwasmFinalizationRegistry _registry = SkwasmFinalizationRegistry( - pathDispose, + (PathHandle handle) => pathDispose(handle), ); @override diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/path_metrics.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/path_metrics.dart index 490ca84fe0a..bb443109890 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/path_metrics.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/path_metrics.dart @@ -24,7 +24,9 @@ class SkwasmPathMetricIterator extends SkwasmObjectWrapper _registry = - SkwasmFinalizationRegistry(contourMeasureIterDispose); + SkwasmFinalizationRegistry( + (ContourMeasureIterHandle handle) => contourMeasureIterDispose(handle), + ); SkwasmPathMetric? _current; int _nextIndex = 0; @@ -59,7 +61,9 @@ class SkwasmPathMetric extends SkwasmObjectWrapper implements SkwasmPathMetric(ContourMeasureHandle handle, this.contourIndex) : super(handle, _registry); static final SkwasmFinalizationRegistry _registry = - SkwasmFinalizationRegistry(contourMeasureDispose); + SkwasmFinalizationRegistry( + (ContourMeasureHandle handle) => contourMeasureDispose(handle), + ); @override final int contourIndex; diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/picture.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/picture.dart index ec90e61bf83..5709a82ee79 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/picture.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/picture.dart @@ -10,7 +10,7 @@ class SkwasmPicture extends SkwasmObjectWrapper implements ScenePict SkwasmPicture.fromHandle(PictureHandle handle) : super(handle, _registry); static final SkwasmFinalizationRegistry _registry = - SkwasmFinalizationRegistry(pictureDispose); + SkwasmFinalizationRegistry((PictureHandle handle) => pictureDispose(handle)); @override Future toImage(int width, int height) async => toImageSync(width, height); @@ -43,7 +43,9 @@ class SkwasmPictureRecorder extends SkwasmObjectWrapper SkwasmPictureRecorder() : super(pictureRecorderCreate(), _registry); static final SkwasmFinalizationRegistry _registry = - SkwasmFinalizationRegistry(pictureRecorderDispose); + SkwasmFinalizationRegistry( + (PictureRecorderHandle handle) => pictureRecorderDispose(handle), + ); @override SkwasmPicture endRecording() { diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/raw/skwasm_module.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/raw/skwasm_module.dart index c1ec710a653..34584f9a51f 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/raw/skwasm_module.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/raw/skwasm_module.dart @@ -9,19 +9,11 @@ import 'dart:_wasm'; import 'dart:ffi'; import 'dart:js_interop'; -@JS() -@staticInterop -class WebAssemblyMemory {} - -extension WebAssemblyMemoryExtension on WebAssemblyMemory { +extension type WebAssemblyMemory._(JSObject _) implements JSObject { external JSArrayBuffer get buffer; } -@JS() -@staticInterop -class SkwasmInstance {} - -extension SkwasmInstanceExtension on SkwasmInstance { +extension type SkwasmInstance._(JSObject _) implements JSObject { external WebAssemblyMemory get wasmMemory; } diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/renderer.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/renderer.dart index 45b706e0a96..e2fc138d32c 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/renderer.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/renderer.dart @@ -362,7 +362,7 @@ class SkwasmRenderer implements Renderer { } final SkwasmImageDecoder decoder = SkwasmImageDecoder( contentType: contentType, - dataSource: response.body as JSObject, + dataSource: response.body, debugSource: uri.toString(), ); await decoder.initialize(); @@ -435,9 +435,9 @@ class SkwasmRenderer implements Renderer { ui.Image createImageFromImageBitmap(DomImageBitmap imageSource) { return SkwasmImage( imageCreateFromTextureSource( - imageSource as JSObject, - imageSource.width.toDartInt, - imageSource.height.toDartInt, + imageSource, + imageSource.width, + imageSource.height, surface.handle, ), ); diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/shaders.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/shaders.dart index 4561c26cd0c..3f7119f1a51 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/shaders.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/shaders.dart @@ -21,7 +21,7 @@ class SkwasmNativeShader extends SkwasmObjectWrapper implements Skwas SkwasmNativeShader(ShaderHandle handle) : super(handle, _registry); static final SkwasmFinalizationRegistry _registry = - SkwasmFinalizationRegistry(shaderDispose); + SkwasmFinalizationRegistry((ShaderHandle handle) => shaderDispose(handle)); } class SkwasmGradient extends SkwasmNativeShader implements ui.Gradient { @@ -223,7 +223,9 @@ class SkwasmFragmentProgram extends SkwasmObjectWrapper } static final SkwasmFinalizationRegistry _registry = - SkwasmFinalizationRegistry(runtimeEffectDispose); + SkwasmFinalizationRegistry( + (RuntimeEffectHandle handle) => runtimeEffectDispose(handle), + ); final String name; final int floatUniformCount; @@ -239,7 +241,7 @@ class SkwasmShaderData extends SkwasmObjectWrapper { SkwasmShaderData(int size) : super(skDataCreate(size), _registry); static final SkwasmFinalizationRegistry _registry = - SkwasmFinalizationRegistry(skDataDispose); + SkwasmFinalizationRegistry((SkDataHandle handle) => skDataDispose(handle)); } // This class does not inherit from SkwasmNativeShader, as its handle might diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/surface.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/surface.dart index 0d873097b87..50ac936130b 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/surface.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/surface.dart @@ -12,14 +12,9 @@ import 'package:ui/src/engine.dart'; import 'package:ui/src/engine/skwasm/skwasm_impl.dart'; import 'package:ui/ui.dart' as ui; -@JS() -@staticInterop -@anonymous -class RasterResult {} - -extension RasterResultExtension on RasterResult { - external JSNumber get rasterStartMilliseconds; - external JSNumber get rasterEndMilliseconds; +extension type RasterResult._(JSObject _) implements JSObject { + external double get rasterStartMilliseconds; + external double get rasterEndMilliseconds; external JSArray get imageBitmaps; } @@ -104,8 +99,8 @@ class SkwasmSurface { (await SkwasmCallbackHandler.instance.registerCallback(callbackId)) as RasterResult; final RenderResult result = ( imageBitmaps: rasterResult.imageBitmaps.toDart.cast(), - rasterStartMicros: (rasterResult.rasterStartMilliseconds.toDartDouble * 1000).toInt(), - rasterEndMicros: (rasterResult.rasterEndMilliseconds.toDartDouble * 1000).toInt(), + rasterStartMicros: (rasterResult.rasterStartMilliseconds * 1000).toInt(), + rasterEndMicros: (rasterResult.rasterEndMilliseconds * 1000).toInt(), ); return result; }); diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/vertices.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/vertices.dart index 1a7c85abfdc..5f22aa899ee 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/vertices.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/vertices.dart @@ -68,5 +68,5 @@ class SkwasmVertices extends SkwasmObjectWrapper implements ui.Vert SkwasmVertices._(VerticesHandle handle) : super(handle, _registry); static final SkwasmFinalizationRegistry _registry = - SkwasmFinalizationRegistry(verticesDispose); + SkwasmFinalizationRegistry((VerticesHandle handle) => verticesDispose(handle)); } diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/svg.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/svg.dart index 718a5c454be..92fb39a493a 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/svg.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/svg.dart @@ -6,20 +6,18 @@ import 'dart:js_interop'; import 'dom.dart'; -@JS() -@staticInterop -class SVGElement extends DomElement {} +extension type SVGElement(JSObject _) implements JSObject, DomElement {} SVGElement createSVGElement(String tag) => domDocument.createElementNS('http://www.w3.org/2000/svg', tag) as SVGElement; -@JS() -@staticInterop -class SVGGraphicsElement extends SVGElement {} +extension type SVGGraphicsElement(JSObject _) implements JSObject, SVGElement {} -@JS() -@staticInterop -class SVGSVGElement extends SVGGraphicsElement {} +extension type SVGSVGElement(JSObject _) implements JSObject, SVGGraphicsElement { + external SVGNumber createSVGNumber(); + external SVGAnimatedLength? get height; + external SVGAnimatedLength? get width; +} SVGSVGElement createSVGSVGElement() { final SVGElement el = createSVGElement('svg'); @@ -27,42 +25,24 @@ SVGSVGElement createSVGSVGElement() { return el as SVGSVGElement; } -extension SVGSVGElementExtension on SVGSVGElement { - external SVGNumber createSVGNumber(); - external SVGAnimatedLength? get height; - external SVGAnimatedLength? get width; -} - -@JS() -@staticInterop -class SVGClipPathElement extends SVGGraphicsElement {} +extension type SVGClipPathElement(JSObject _) implements JSObject, SVGGraphicsElement {} SVGClipPathElement createSVGClipPathElement() => domDocument.createElementNS('http://www.w3.org/2000/svg', 'clipPath') as SVGClipPathElement; -@JS() -@staticInterop -class SVGDefsElement extends SVGGraphicsElement {} +extension type SVGDefsElement(JSObject _) implements JSObject, SVGGraphicsElement {} SVGDefsElement createSVGDefsElement() => domDocument.createElementNS('http://www.w3.org/2000/svg', 'defs') as SVGDefsElement; -@JS() -@staticInterop -class SVGGeometryElement extends SVGGraphicsElement {} +extension type SVGGeometryElement(JSObject _) implements JSObject, SVGGraphicsElement {} -@JS() -@staticInterop -class SVGPathElement extends SVGGeometryElement {} +extension type SVGPathElement(JSObject _) implements JSObject, SVGGeometryElement {} SVGPathElement createSVGPathElement() => domDocument.createElementNS('http://www.w3.org/2000/svg', 'path') as SVGPathElement; -@JS() -@staticInterop -class SVGFilterElement extends SVGElement {} - -extension SVGFilterElementExtension on SVGFilterElement { +extension type SVGFilterElement(JSObject _) implements JSObject, SVGElement { external SVGAnimatedEnumeration? get filterUnits; external SVGAnimatedLength? get height; external SVGAnimatedLength? get width; @@ -73,46 +53,22 @@ extension SVGFilterElementExtension on SVGFilterElement { SVGFilterElement createSVGFilterElement() => domDocument.createElementNS('http://www.w3.org/2000/svg', 'filter') as SVGFilterElement; -@JS() -@staticInterop -class SVGAnimatedLength {} - -extension SVGAnimatedLengthExtension on SVGAnimatedLength { +extension type SVGAnimatedLength(JSObject _) implements JSObject { external SVGLength? get baseVal; } -@JS() -@staticInterop -class SVGLength {} - -extension SVGLengthExtension on SVGLength { - @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); +extension type SVGLength(JSObject _) implements JSObject { + external set valueAsString(String? value); + external void newValueSpecifiedUnits(int unitType, num valueInSpecifiedUnits); } const int svgLengthTypeNumber = 1; -@JS() -@staticInterop -class SVGAnimatedEnumeration {} - -extension SVGAnimatedEnumerationExtenson on SVGAnimatedEnumeration { - @JS('baseVal') - external set _baseVal(JSNumber? value); - set baseVal(int? value) => _baseVal = value?.toJS; +extension type SVGAnimatedEnumeration(JSObject _) implements JSObject { + external set baseVal(int? value); } -@JS() -@staticInterop -class SVGFEColorMatrixElement extends SVGElement {} - -extension SVGFEColorMatrixElementExtension on SVGFEColorMatrixElement { +extension type SVGFEColorMatrixElement(JSObject _) implements JSObject, SVGElement { external SVGAnimatedEnumeration? get type; external SVGAnimatedString? get result; external SVGAnimatedNumberList? get values; @@ -122,22 +78,14 @@ SVGFEColorMatrixElement createSVGFEColorMatrixElement() => domDocument.createElementNS('http://www.w3.org/2000/svg', 'feColorMatrix') as SVGFEColorMatrixElement; -@JS() -@staticInterop -class SVGFEFloodElement extends SVGElement {} - -extension SVGFEFloodElementExtension on SVGFEFloodElement { +extension type SVGFEFloodElement(JSObject _) implements JSObject, SVGElement { external SVGAnimatedString? get result; } SVGFEFloodElement createSVGFEFloodElement() => domDocument.createElementNS('http://www.w3.org/2000/svg', 'feFlood') as SVGFEFloodElement; -@JS() -@staticInterop -class SVGFEBlendElement extends SVGElement {} - -extension SVGFEBlendElementExtension on SVGFEBlendElement { +extension type SVGFEBlendElement(JSObject _) implements JSObject, SVGElement { external SVGAnimatedString? get in1; external SVGAnimatedString? get in2; external SVGAnimatedEnumeration? get mode; @@ -146,11 +94,7 @@ extension SVGFEBlendElementExtension on SVGFEBlendElement { SVGFEBlendElement createSVGFEBlendElement() => domDocument.createElementNS('http://www.w3.org/2000/svg', 'feBlend') as SVGFEBlendElement; -@JS() -@staticInterop -class SVGFEImageElement extends SVGElement {} - -extension SVGFEImageElementExtension on SVGFEImageElement { +extension type SVGFEImageElement(JSObject _) implements JSObject, SVGElement { external SVGAnimatedLength? get height; external SVGAnimatedLength? get width; external SVGAnimatedString? get result; @@ -162,15 +106,7 @@ extension SVGFEImageElementExtension on SVGFEImageElement { SVGFEImageElement createSVGFEImageElement() => domDocument.createElementNS('http://www.w3.org/2000/svg', 'feImage') as SVGFEImageElement; -@JS() -@staticInterop -class SVGFECompositeElement extends SVGElement {} - -SVGFECompositeElement createSVGFECompositeElement() => - domDocument.createElementNS('http://www.w3.org/2000/svg', 'feComposite') - as SVGFECompositeElement; - -extension SVGFEBlendCompositeExtension on SVGFECompositeElement { +extension type SVGFECompositeElement(JSObject _) implements JSObject, SVGElement { external SVGAnimatedString? get in1; external SVGAnimatedString? get in2; external SVGAnimatedNumber? get k1; @@ -181,48 +117,26 @@ extension SVGFEBlendCompositeExtension on SVGFECompositeElement { external SVGAnimatedString? get result; } -@JS() -@staticInterop -class SVGAnimatedString {} +SVGFECompositeElement createSVGFECompositeElement() => + domDocument.createElementNS('http://www.w3.org/2000/svg', 'feComposite') + as SVGFECompositeElement; -extension SVGAnimatedStringExtension on SVGAnimatedString { - @JS('baseVal') - external set _baseVal(JSString? value); - set baseVal(String? value) => _baseVal = value?.toJS; +extension type SVGAnimatedString(JSObject _) implements JSObject { + external set baseVal(String? value); } -@JS() -@staticInterop -class SVGAnimatedNumber {} - -extension SVGAnimatedNumberExtension on SVGAnimatedNumber { - @JS('baseVal') - external set _baseVal(JSNumber? value); - set baseVal(num? value) => _baseVal = value?.toJS; +extension type SVGAnimatedNumber(JSObject _) implements JSObject { + external set baseVal(num? value); } -@JS() -@staticInterop -class SVGAnimatedNumberList {} - -extension SVGAnimatedNumberListExtension on SVGAnimatedNumberList { +extension type SVGAnimatedNumberList(JSObject _) implements JSObject { external SVGNumberList? get baseVal; } -@JS() -@staticInterop -class SVGNumberList {} - -extension SVGNumberListExtension on SVGNumberList { +extension type SVGNumberList(JSObject _) implements JSObject { external SVGNumber appendItem(SVGNumber newItem); } -@JS() -@staticInterop -class SVGNumber {} - -extension SVGNumberExtension on SVGNumber { - @JS('value') - external set _value(JSNumber? value); - set value(num? v) => _value = v?.toJS; +extension type SVGNumber(JSObject _) implements JSObject { + external set value(num? v); } diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/text_editing/composition_aware_mixin.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/text_editing/composition_aware_mixin.dart index d471fa763be..a3915dfb95f 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/text_editing/composition_aware_mixin.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/text_editing/composition_aware_mixin.dart @@ -59,17 +59,17 @@ mixin CompositionAwareMixin { domElement.removeEventListener(_kCompositionEnd, _compositionEndListener); } - JSVoid _handleCompositionStart(DomEvent event) { + void _handleCompositionStart(DomEvent event) { composingText = null; } - JSVoid _handleCompositionUpdate(DomEvent event) { - if (domInstanceOfString(event, 'CompositionEvent')) { + void _handleCompositionUpdate(DomEvent event) { + if (event.isA()) { composingText = (event as DomCompositionEvent).data; } } - JSVoid _handleCompositionEnd(DomEvent event) { + void _handleCompositionEnd(DomEvent event) { composingText = null; } diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/text_editing/text_capitalization.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/text_editing/text_capitalization.dart index 5bf69ade830..a153dd7bcdb 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/text_editing/text_capitalization.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/text_editing/text_capitalization.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 '../dom.dart'; /// Controls the capitalization of the text. @@ -68,10 +70,10 @@ class TextCapitalizationConfig { case TextCapitalization.none: autocapitalize = 'off'; } - if (domInstanceOfString(domElement, 'HTMLInputElement')) { + if (domElement.isA()) { final DomHTMLInputElement element = domElement as DomHTMLInputElement; element.setAttribute('autocapitalize', autocapitalize); - } else if (domInstanceOfString(domElement, 'HTMLTextAreaElement')) { + } else if (domElement.isA()) { final DomHTMLTextAreaElement element = domElement as DomHTMLTextAreaElement; element.setAttribute('autocapitalize', autocapitalize); } diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/text_editing/text_editing.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/text_editing/text_editing.dart index eb0cd4f66c7..79aae60ac65 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/text_editing/text_editing.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/text_editing/text_editing.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'dart:async'; +import 'dart:js_interop'; import 'dart:math' as math; import 'dart:typed_data'; @@ -390,14 +391,18 @@ class EngineAutofillForm { void addSubscriptionForKey(String key) { final DomElement element = elements![key]!; subscriptions.add( - DomSubscription(element, 'input', (DomEvent e) { - if (items![key] == null) { - throw StateError('AutofillInfo must have a valid uniqueIdentifier.'); - } else { - final AutofillInfo autofillInfo = items![key]!; - handleChange(element, autofillInfo); - } - }), + DomSubscription( + element, + 'input', + createDomEventListener((DomEvent e) { + if (items![key] == null) { + throw StateError('AutofillInfo must have a valid uniqueIdentifier.'); + } else { + final AutofillInfo autofillInfo = items![key]!; + handleChange(element, autofillInfo); + } + }), + ), ); } @@ -502,7 +507,7 @@ class AutofillInfo { void applyToDomElement(DomHTMLElement domElement, {bool focusedElement = false}) { final String? autofillHint = this.autofillHint; final String? placeholder = this.placeholder; - if (domInstanceOfString(domElement, 'HTMLInputElement')) { + if (domElement.isA()) { final DomHTMLInputElement element = domElement as DomHTMLInputElement; if (placeholder != null) { element.placeholder = placeholder; @@ -517,7 +522,7 @@ class AutofillInfo { } } element.autocomplete = autofillHint ?? 'on'; - } else if (domInstanceOfString(domElement, 'HTMLTextAreaElement')) { + } else if (domElement.isA()) { final DomHTMLTextAreaElement element = domElement as DomHTMLTextAreaElement; if (placeholder != null) { element.placeholder = placeholder; @@ -830,8 +835,8 @@ class EditingState { /// [domElement] can be a [InputElement] or a [TextAreaElement] depending on /// the [InputType] of the text field. factory EditingState.fromDomElement(DomHTMLElement? domElement) { - if (domInstanceOfString(domElement, 'HTMLInputElement')) { - final DomHTMLInputElement element = domElement! as DomHTMLInputElement; + if (domElement != null && domElement.isA()) { + final DomHTMLInputElement element = domElement as DomHTMLInputElement; if (element.selectionDirection == 'backward') { return EditingState( text: element.value, @@ -845,8 +850,8 @@ class EditingState { extentOffset: element.selectionEnd?.toInt(), ); } - } else if (domInstanceOfString(domElement, 'HTMLTextAreaElement')) { - final DomHTMLTextAreaElement element = domElement! as DomHTMLTextAreaElement; + } else if (domElement != null && domElement.isA()) { + final DomHTMLTextAreaElement element = domElement as DomHTMLTextAreaElement; if (element.selectionDirection == 'backward') { return EditingState( text: element.value, @@ -959,12 +964,12 @@ class EditingState { /// /// * [applyTextToDomElement], which is used for non-focused elements. void applyToDomElement(DomHTMLElement? domElement) { - if (domInstanceOfString(domElement, 'HTMLInputElement')) { - final DomHTMLInputElement element = domElement! as DomHTMLInputElement; + if (domElement != null && domElement.isA()) { + final DomHTMLInputElement element = domElement as DomHTMLInputElement; element.value = text; element.setSelectionRange(minOffset, maxOffset); - } else if (domInstanceOfString(domElement, 'HTMLTextAreaElement')) { - final DomHTMLTextAreaElement element = domElement! as DomHTMLTextAreaElement; + } else if (domElement != null && domElement.isA()) { + final DomHTMLTextAreaElement element = domElement as DomHTMLTextAreaElement; element.value = text; element.setSelectionRange(minOffset, maxOffset); } else { @@ -982,11 +987,11 @@ class EditingState { /// /// * [applyToDomElement], which is used for focused elements. void applyTextToDomElement(DomHTMLElement? domElement) { - if (domInstanceOfString(domElement, 'HTMLInputElement')) { - final DomHTMLInputElement element = domElement! as DomHTMLInputElement; + if (domElement != null && domElement.isA()) { + final DomHTMLInputElement element = domElement as DomHTMLInputElement; element.value = text; - } else if (domInstanceOfString(domElement, 'HTMLTextAreaElement')) { - final DomHTMLTextAreaElement element = domElement! as DomHTMLTextAreaElement; + } else if (domElement != null && domElement.isA()) { + final DomHTMLTextAreaElement element = domElement as DomHTMLTextAreaElement; element.value = text; } else { throw UnsupportedError('Unsupported DOM element type'); @@ -1363,18 +1368,28 @@ abstract class DefaultTextEditingStrategy } // Subscribe to text and selection changes. - subscriptions.add(DomSubscription(activeDomElement, 'input', handleChange)); + subscriptions.add( + DomSubscription(activeDomElement, 'input', createDomEventListener(handleChange)), + ); - subscriptions.add(DomSubscription(activeDomElement, 'keydown', maybeSendAction)); + subscriptions.add( + DomSubscription(activeDomElement, 'keydown', createDomEventListener(maybeSendAction)), + ); - subscriptions.add(DomSubscription(domDocument, 'selectionchange', handleChange)); + subscriptions.add( + DomSubscription(domDocument, 'selectionchange', createDomEventListener(handleChange)), + ); - subscriptions.add(DomSubscription(activeDomElement, 'beforeinput', handleBeforeInput)); + subscriptions.add( + DomSubscription(activeDomElement, 'beforeinput', createDomEventListener(handleBeforeInput)), + ); if (this is! SafariDesktopTextEditingStrategy) { // handleBlur causes Safari to reopen autofill dialogs after autofill, // so we don't attach the listener there. - subscriptions.add(DomSubscription(activeDomElement, 'blur', handleBlur)); + subscriptions.add( + DomSubscription(activeDomElement, 'blur', createDomEventListener(handleBlur)), + ); } addCompositionEventHandlers(activeDomElement); @@ -1529,7 +1544,7 @@ abstract class DefaultTextEditingStrategy } void maybeSendAction(DomEvent e) { - if (domInstanceOfString(e, 'KeyboardEvent')) { + if (e.isA()) { final DomKeyboardEvent event = e as DomKeyboardEvent; if (event.keyCode == _kReturnKeyCode) { onAction!(inputConfiguration.inputAction); @@ -1580,21 +1595,33 @@ abstract class DefaultTextEditingStrategy /// see: https://bugs.chromium.org/p/chromium/issues/detail?id=119216#c11. void preventDefaultForMouseEvents() { subscriptions.add( - DomSubscription(activeDomElement, 'mousedown', (DomEvent event) { - event.preventDefault(); - }), + DomSubscription( + activeDomElement, + 'mousedown', + createDomEventListener((DomEvent event) { + event.preventDefault(); + }), + ), ); subscriptions.add( - DomSubscription(activeDomElement, 'mouseup', (DomEvent event) { - event.preventDefault(); - }), + DomSubscription( + activeDomElement, + 'mouseup', + createDomEventListener((DomEvent event) { + event.preventDefault(); + }), + ), ); subscriptions.add( - DomSubscription(activeDomElement, 'mousemove', (DomEvent event) { - event.preventDefault(); - }), + DomSubscription( + activeDomElement, + 'mousemove', + createDomEventListener((DomEvent event) { + event.preventDefault(); + }), + ), ); } @@ -1679,24 +1706,38 @@ class IOSTextEditingStrategy extends GloballyPositionedTextEditingStrategy { } // Subscribe to text and selection changes. - subscriptions.add(DomSubscription(activeDomElement, 'input', handleChange)); + subscriptions.add( + DomSubscription(activeDomElement, 'input', createDomEventListener(handleChange)), + ); - subscriptions.add(DomSubscription(activeDomElement, 'keydown', maybeSendAction)); + subscriptions.add( + DomSubscription(activeDomElement, 'keydown', createDomEventListener(maybeSendAction)), + ); - subscriptions.add(DomSubscription(domDocument, 'selectionchange', handleChange)); + subscriptions.add( + DomSubscription(domDocument, 'selectionchange', createDomEventListener(handleChange)), + ); - subscriptions.add(DomSubscription(activeDomElement, 'beforeinput', handleBeforeInput)); + subscriptions.add( + DomSubscription(activeDomElement, 'beforeinput', createDomEventListener(handleBeforeInput)), + ); - subscriptions.add(DomSubscription(activeDomElement, 'blur', handleBlur)); + subscriptions.add( + DomSubscription(activeDomElement, 'blur', createDomEventListener(handleBlur)), + ); addCompositionEventHandlers(activeDomElement); // Position the DOM element after it is focused. subscriptions.add( - DomSubscription(activeDomElement, 'focus', (_) { - // Cancel previous timer if exists. - _schedulePlacement(); - }), + DomSubscription( + activeDomElement, + 'focus', + createDomEventListener((DomEvent _) { + // Cancel previous timer if exists. + _schedulePlacement(); + }), + ), ); _addTapListener(); @@ -1736,18 +1777,22 @@ class IOSTextEditingStrategy extends GloballyPositionedTextEditingStrategy { /// placed to its correct position after [_delayBeforePlacement]. void _addTapListener() { subscriptions.add( - DomSubscription(activeDomElement, 'click', (_) { - // Check if the element is already positioned. If not this does not fall - // under `The user was using the long press, now they want to enter text - // via keyboard` journey. - if (_canPosition) { - // Re-place the element somewhere outside of the screen. - initializeElementPlacement(); + DomSubscription( + activeDomElement, + 'click', + createDomEventListener((DomEvent _) { + // Check if the element is already positioned. If not this does not fall + // under `The user was using the long press, now they want to enter text + // via keyboard` journey. + if (_canPosition) { + // Re-place the element somewhere outside of the screen. + initializeElementPlacement(); - // Re-configure the timer to place the element. - _schedulePlacement(); - } - }), + // Re-configure the timer to place the element. + _schedulePlacement(); + } + }), + ), ); } @@ -1799,15 +1844,25 @@ class AndroidTextEditingStrategy extends GloballyPositionedTextEditingStrategy { } // Subscribe to text and selection changes. - subscriptions.add(DomSubscription(activeDomElement, 'input', handleChange)); + subscriptions.add( + DomSubscription(activeDomElement, 'input', createDomEventListener(handleChange)), + ); - subscriptions.add(DomSubscription(activeDomElement, 'keydown', maybeSendAction)); + subscriptions.add( + DomSubscription(activeDomElement, 'keydown', createDomEventListener(maybeSendAction)), + ); - subscriptions.add(DomSubscription(domDocument, 'selectionchange', handleChange)); + subscriptions.add( + DomSubscription(domDocument, 'selectionchange', createDomEventListener(handleChange)), + ); - subscriptions.add(DomSubscription(activeDomElement, 'beforeinput', handleBeforeInput)); + subscriptions.add( + DomSubscription(activeDomElement, 'beforeinput', createDomEventListener(handleBeforeInput)), + ); - subscriptions.add(DomSubscription(activeDomElement, 'blur', handleBlur)); + subscriptions.add( + DomSubscription(activeDomElement, 'blur', createDomEventListener(handleBlur)), + ); addCompositionEventHandlers(activeDomElement); @@ -1847,11 +1902,17 @@ class FirefoxTextEditingStrategy extends GloballyPositionedTextEditingStrategy { } // Subscribe to text and selection changes. - subscriptions.add(DomSubscription(activeDomElement, 'input', handleChange)); + subscriptions.add( + DomSubscription(activeDomElement, 'input', createDomEventListener(handleChange)), + ); - subscriptions.add(DomSubscription(activeDomElement, 'keydown', maybeSendAction)); + subscriptions.add( + DomSubscription(activeDomElement, 'keydown', createDomEventListener(maybeSendAction)), + ); - subscriptions.add(DomSubscription(activeDomElement, 'beforeinput', handleBeforeInput)); + subscriptions.add( + DomSubscription(activeDomElement, 'beforeinput', createDomEventListener(handleBeforeInput)), + ); addCompositionEventHandlers(activeDomElement); @@ -1869,17 +1930,25 @@ class FirefoxTextEditingStrategy extends GloballyPositionedTextEditingStrategy { // After each keyup, the start/end values of the selection is compared to // the previously saved editing state. subscriptions.add( - DomSubscription(activeDomElement, 'keyup', (DomEvent event) { - handleChange(event); - }), + DomSubscription( + activeDomElement, + 'keyup', + createDomEventListener((DomEvent event) { + handleChange(event); + }), + ), ); // In Firefox the context menu item "Select All" does not work without // listening to onSelect. On the other browsers onSelectionChange is // enough for covering "Select All" functionality. - subscriptions.add(DomSubscription(activeDomElement, 'select', handleChange)); + subscriptions.add( + DomSubscription(activeDomElement, 'select', createDomEventListener(handleChange)), + ); - subscriptions.add(DomSubscription(activeDomElement, 'blur', handleBlur)); + subscriptions.add( + DomSubscription(activeDomElement, 'blur', createDomEventListener(handleBlur)), + ); preventDefaultForMouseEvents(); } diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/view_embedder/dimensions_provider/full_page_dimensions_provider.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/view_embedder/dimensions_provider/full_page_dimensions_provider.dart index d7edf4220bb..e95da63b342 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/view_embedder/dimensions_provider/full_page_dimensions_provider.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/view_embedder/dimensions_provider/full_page_dimensions_provider.dart @@ -29,7 +29,11 @@ class FullPageDimensionsProvider extends DimensionsProvider { final DomEventTarget resizeEventTarget = domWindow.visualViewport ?? domWindow; // Subscribe to the 'resize' event, and convert it to a ui.Size stream. - _domResizeSubscription = DomSubscription(resizeEventTarget, 'resize', _onVisualViewportResize); + _domResizeSubscription = DomSubscription( + resizeEventTarget, + 'resize', + createDomEventListener(_onVisualViewportResize), + ); } late DomSubscription _domResizeSubscription; diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/view_embedder/display_dpr_stream.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/view_embedder/display_dpr_stream.dart index 4bb8d8fd26f..0b330e13b9c 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/view_embedder/display_dpr_stream.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/view_embedder/display_dpr_stream.dart @@ -3,7 +3,6 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:js_interop'; import 'package:meta/meta.dart'; import 'package:ui/src/engine/display.dart'; @@ -47,7 +46,7 @@ class DisplayDprStream { } else { _dprMediaQuery = domWindow.matchMedia('(resolution: ${_currentDpr}dppx)'); } - _dprMediaQuery.addEventListenerWithOptions( + _dprMediaQuery.addEventListener( 'change', createDomEventListener(_onDprMediaQueryChange), { @@ -59,14 +58,14 @@ class DisplayDprStream { // listener from the old mediaQuery after we're done with it. 'once': true, 'passive': true, - }, + }.toJSAnyDeep, ); } // Handler of the _dprMediaQuery 'change' event. // // This calls subscribe again because events are listened to with `once: true`. - JSVoid _onDprMediaQueryChange(DomEvent _) { + void _onDprMediaQueryChange(DomEvent _) { _currentDpr = _display.devicePixelRatio; _dprStreamController.add(_currentDpr); // Re-subscribe... diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/view_embedder/hot_restart_cache_handler.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/view_embedder/hot_restart_cache_handler.dart index eb8be79747b..186f0e485b9 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/view_embedder/hot_restart_cache_handler.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/view_embedder/hot_restart_cache_handler.dart @@ -53,7 +53,7 @@ class HotRestartCacheHandler { /// Registers a [DomElement] to be removed after hot-restart. @visibleForTesting void registerElement(DomElement element) { - _jsHotRestartStore!.push(element as JSObject); + _jsHotRestartStore!.push(element); } } diff --git a/engine/src/flutter/lib/web_ui/lib/ui_web/src/ui_web/browser_detection.dart b/engine/src/flutter/lib/web_ui/lib/ui_web/src/ui_web/browser_detection.dart index a3d816e4553..a512a293e0b 100644 --- a/engine/src/flutter/lib/web_ui/lib/ui_web/src/ui_web/browser_detection.dart +++ b/engine/src/flutter/lib/web_ui/lib/ui_web/src/ui_web/browser_detection.dart @@ -4,7 +4,7 @@ import 'package:meta/meta.dart'; -import 'package:ui/src/engine/dom.dart' show DomNavigatorExtension, DomWindowExtension, domWindow; +import 'package:ui/src/engine/dom.dart' show domWindow; /// The HTML engine used by the current browser. enum BrowserEngine { diff --git a/engine/src/flutter/lib/web_ui/lib/ui_web/src/ui_web/images.dart b/engine/src/flutter/lib/web_ui/lib/ui_web/src/ui_web/images.dart index eb53016ba93..bbfe990c883 100644 --- a/engine/src/flutter/lib/web_ui/lib/ui_web/src/ui_web/images.dart +++ b/engine/src/flutter/lib/web_ui/lib/ui_web/src/ui_web/images.dart @@ -28,7 +28,7 @@ Future createImageCodecFromUrl(Uri uri, {ImageCodecChunkCallback? chun /// /// See https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap FutureOr createImageFromImageBitmap(JSAny imageSource) { - if (!domInstanceOfString(imageSource, 'ImageBitmap')) { + if (!imageSource.isA()) { throw ArgumentError('Image source $imageSource is not an ImageBitmap.', 'imageSource'); } return renderer.createImageFromImageBitmap(imageSource as DomImageBitmap); diff --git a/engine/src/flutter/lib/web_ui/lib/ui_web/src/ui_web/navigation/platform_location.dart b/engine/src/flutter/lib/web_ui/lib/ui_web/src/ui_web/navigation/platform_location.dart index a4764546494..8b0dd342e8c 100644 --- a/engine/src/flutter/lib/web_ui/lib/ui_web/src/ui_web/navigation/platform_location.dart +++ b/engine/src/flutter/lib/web_ui/lib/ui_web/src/ui_web/navigation/platform_location.dart @@ -89,7 +89,10 @@ class BrowserPlatformLocation implements PlatformLocation { @visibleForTesting DomEventListener getOrCreateDomEventListener(EventListener fn) { - return _popStateListenersCache.putIfAbsent(fn, () => createDomEventListener(fn)); + final DomEventListener jsListener = createDomEventListener((DomEvent event) { + fn(event); + }); + return _popStateListenersCache.putIfAbsent(fn, () => jsListener); } @override @@ -114,7 +117,7 @@ class BrowserPlatformLocation implements PlatformLocation { String get search => _location.search!; @override - String get hash => _location.locationHash; + String get hash => _location.hash; @override Object? get state => _history.state; diff --git a/engine/src/flutter/lib/web_ui/pubspec.yaml b/engine/src/flutter/lib/web_ui/pubspec.yaml index 6c5699c8881..d25e1678790 100644 --- a/engine/src/flutter/lib/web_ui/pubspec.yaml +++ b/engine/src/flutter/lib/web_ui/pubspec.yaml @@ -6,7 +6,6 @@ environment: sdk: ^3.7.0-0 dependencies: - js: ^0.7.0 meta: ^1.14.0 web_locale_keymap: path: ../../third_party/web_locale_keymap diff --git a/engine/src/flutter/lib/web_ui/test/canvaskit/canvas_golden_test.dart b/engine/src/flutter/lib/web_ui/test/canvaskit/canvas_golden_test.dart index fba554c7e8a..ef67ffde787 100644 --- a/engine/src/flutter/lib/web_ui/test/canvaskit/canvas_golden_test.dart +++ b/engine/src/flutter/lib/web_ui/test/canvaskit/canvas_golden_test.dart @@ -477,7 +477,7 @@ void drawTestPicture(CkCanvas canvas) { } CkImage generateTestImage() { - final DomCanvasElement canvas = createDomCanvasElement(width: 20, height: 20); + final DomHTMLCanvasElement canvas = createDomCanvasElement(width: 20, height: 20); final DomCanvasRenderingContext2D ctx = canvas.context2D; ctx.fillStyle = '#FF0000'; ctx.fillRect(0, 0, 10, 10); diff --git a/engine/src/flutter/lib/web_ui/test/canvaskit/canvaskit_api_test.dart b/engine/src/flutter/lib/web_ui/test/canvaskit/canvaskit_api_test.dart index 011af1451aa..806dcf2e31a 100644 --- a/engine/src/flutter/lib/web_ui/test/canvaskit/canvaskit_api_test.dart +++ b/engine/src/flutter/lib/web_ui/test/canvaskit/canvaskit_api_test.dart @@ -1573,7 +1573,7 @@ void _paragraphTests() { final SkParagraph paragraph = builder.build(); paragraph.layout(500); - final DomCanvasElement canvas = createDomCanvasElement(width: 400, height: 160); + final DomHTMLCanvasElement canvas = createDomCanvasElement(width: 400, height: 160); domDocument.body!.append(canvas); // TODO(yjbanov): WebGL screenshot tests do not work on Firefox - https://github.com/flutter/flutter/issues/109265 @@ -1721,7 +1721,7 @@ void _paragraphTests() { test( 'MakeOnScreenGLSurface test', () { - final DomCanvasElement canvas = createDomCanvasElement(width: 100, height: 100); + final DomHTMLCanvasElement canvas = createDomCanvasElement(width: 100, height: 100); final WebGLContext gl = canvas.getGlContext(webGLVersion); final int sampleCount = gl.getParameter(gl.samples); final int stencilBits = gl.getParameter(gl.stencilBits); @@ -1748,7 +1748,7 @@ void _paragraphTests() { test( 'MakeRenderTarget test', () { - final DomCanvasElement canvas = createDomCanvasElement(width: 100, height: 100); + final DomHTMLCanvasElement canvas = createDomCanvasElement(width: 100, height: 100); final int glContext = canvasKit.GetWebGLContext( diff --git a/engine/src/flutter/lib/web_ui/test/canvaskit/image_golden_test.dart b/engine/src/flutter/lib/web_ui/test/canvaskit/image_golden_test.dart index 27faf8ec34a..d8d08c78edc 100644 --- a/engine/src/flutter/lib/web_ui/test/canvaskit/image_golden_test.dart +++ b/engine/src/flutter/lib/web_ui/test/canvaskit/image_golden_test.dart @@ -100,7 +100,7 @@ class BitmapTestCodec extends TestFileCodec { await imageElement.decode(); - final DomImageBitmap bitmap = await createImageBitmap(imageElement as JSObject, ( + final DomImageBitmap bitmap = await createImageBitmap(imageElement, ( x: 0, y: 0, width: imageElement.naturalWidth.toInt(), @@ -138,7 +138,8 @@ class BitmapSingleFrameCodec implements ui.Codec { Future testMain() async { final HttpFetchResponse listingResponse = await httpFetch('/test_images/'); - final List testFiles = (await listingResponse.json() as List).cast(); + final List testFiles = + ((await listingResponse.json() as JSAny?).dartify()! as List).cast(); List createTestCodecs({int testTargetWidth = 300, int testTargetHeight = 300}) { // Sanity-check the test file list. If suddenly test files are moved or diff --git a/engine/src/flutter/lib/web_ui/test/canvaskit/initialization/does_not_mock_module_exports_test.dart b/engine/src/flutter/lib/web_ui/test/canvaskit/initialization/does_not_mock_module_exports_test.dart index 1ab657b504e..9673cfe26cb 100644 --- a/engine/src/flutter/lib/web_ui/test/canvaskit/initialization/does_not_mock_module_exports_test.dart +++ b/engine/src/flutter/lib/web_ui/test/canvaskit/initialization/does_not_mock_module_exports_test.dart @@ -2,7 +2,6 @@ // 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 'dart:js_interop_unsafe'; import 'package:test/bootstrap/browser.dart'; @@ -22,16 +21,8 @@ void testMain() { await bootstrapAndRunApp(); // window.exports and window.module should be undefined! - expect( - (domWindow as JSObject).has('exports'), - isFalse, - reason: '`window.exports` should not be defined.', - ); - expect( - (domWindow as JSObject).has('module'), - isFalse, - reason: '`window.module` should not be defined.', - ); + expect(domWindow.has('exports'), isFalse, reason: '`window.exports` should not be defined.'); + expect(domWindow.has('module'), isFalse, reason: '`window.module` should not be defined.'); }); }); } diff --git a/engine/src/flutter/lib/web_ui/test/canvaskit/initialization/stores_config_test.dart b/engine/src/flutter/lib/web_ui/test/canvaskit/initialization/stores_config_test.dart index 57248ac262e..54ac615d8b3 100644 --- a/engine/src/flutter/lib/web_ui/test/canvaskit/initialization/stores_config_test.dart +++ b/engine/src/flutter/lib/web_ui/test/canvaskit/initialization/stores_config_test.dart @@ -17,7 +17,7 @@ void testMain() { group('initializeEngineServices', () { test('stores user configuration', () async { final JsFlutterConfiguration config = JsFlutterConfiguration(); - (config as JSObject) + config // `canvasKitBaseUrl` is required for the test to actually run. ..['canvasKitBaseUrl'] = '/canvaskit/'.toJS // A property under test, that we'll try to read later. @@ -26,7 +26,7 @@ void testMain() { ..['nonexistentProperty'] = 32.0.toJS; // Remove window.flutterConfiguration (if it's there) - (domWindow as JSObject)['flutterConfiguration'] = null; + config['flutterConfiguration'] = null; // TODO(web): Replace the above nullification by the following assertion // when wasm and JS tests initialize their config the same way: diff --git a/engine/src/flutter/lib/web_ui/test/canvaskit/native_memory_test.dart b/engine/src/flutter/lib/web_ui/test/canvaskit/native_memory_test.dart index 3cec2cd3806..169ab47b89e 100644 --- a/engine/src/flutter/lib/web_ui/test/canvaskit/native_memory_test.dart +++ b/engine/src/flutter/lib/web_ui/test/canvaskit/native_memory_test.dart @@ -252,10 +252,7 @@ class TestSkDeletableMock { JsConstructor get constructor => TestJsConstructor(name: 'TestSkDeletable'); } -@JS() -@anonymous -@staticInterop -class TestSkDeletable implements SkDeletable { +extension type TestSkDeletable._primary(JSObject _) implements SkDeletable { factory TestSkDeletable() { final TestSkDeletableMock mock = TestSkDeletableMock(); return TestSkDeletable._( @@ -278,10 +275,7 @@ class TestSkDeletable implements SkDeletable { }); } -@JS() -@anonymous -@staticInterop -class TestJsConstructor implements JsConstructor { +extension type TestJsConstructor._(JSObject _) implements JsConstructor { external factory TestJsConstructor({String name}); } @@ -323,7 +317,7 @@ class _MockNativeMemoryFinalizationRegistry implements NativeMemoryFinalizationR final List<_MockPair> registeredPairs = <_MockPair>[]; @override - void register(Object owner, UniqueRef ref) { + void register(Object owner, UniqueRef ref) { registeredPairs.add(_MockPair(owner, ref)); } } @@ -332,5 +326,5 @@ class _MockPair { _MockPair(this.owner, this.ref); Object owner; - UniqueRef ref; + UniqueRef ref; } diff --git a/engine/src/flutter/lib/web_ui/test/canvaskit/surface_test.dart b/engine/src/flutter/lib/web_ui/test/canvaskit/surface_test.dart index bd49152faae..13c9955eae7 100644 --- a/engine/src/flutter/lib/web_ui/test/canvaskit/surface_test.dart +++ b/engine/src/flutter/lib/web_ui/test/canvaskit/surface_test.dart @@ -112,7 +112,7 @@ void testMain() { final Surface surface = Surface(isDisplayCanvas: true); surface.createOrUpdateSurface(const BitmapSize(9, 19)); - final DomCanvasElement original = getDisplayCanvas(surface); + final DomHTMLCanvasElement original = getDisplayCanvas(surface); ui.Size canvasSize = getCssSize(surface); // Expect exact requested dimensions. @@ -123,7 +123,7 @@ void testMain() { // Shrinking causes us to resize the canvas. surface.createOrUpdateSurface(const BitmapSize(5, 15)); - final DomCanvasElement shrunk = getDisplayCanvas(surface); + final DomHTMLCanvasElement shrunk = getDisplayCanvas(surface); canvasSize = getCssSize(surface); expect(shrunk.width, 5); expect(shrunk.height, 15); @@ -132,7 +132,7 @@ void testMain() { // Increasing the size causes us to resize the canvas. surface.createOrUpdateSurface(const BitmapSize(10, 20)); - final DomCanvasElement firstIncrease = getDisplayCanvas(surface); + final DomHTMLCanvasElement firstIncrease = getDisplayCanvas(surface); canvasSize = getCssSize(surface); expect(firstIncrease, same(original)); @@ -145,7 +145,7 @@ void testMain() { // Subsequent increases also cause canvas resizing. surface.createOrUpdateSurface(const BitmapSize(11, 22)); - final DomCanvasElement secondIncrease = getDisplayCanvas(surface); + final DomHTMLCanvasElement secondIncrease = getDisplayCanvas(surface); canvasSize = getCssSize(surface); expect(secondIncrease, same(firstIncrease)); @@ -156,7 +156,7 @@ void testMain() { // Increases beyond the 40% limit will cause a canvas resize. surface.createOrUpdateSurface(const BitmapSize(20, 40)); - final DomCanvasElement huge = getDisplayCanvas(surface); + final DomHTMLCanvasElement huge = getDisplayCanvas(surface); canvasSize = getCssSize(surface); expect(huge, same(secondIncrease)); @@ -169,7 +169,7 @@ void testMain() { // Shrink again. Resize the canvas. surface.createOrUpdateSurface(const BitmapSize(5, 15)); - final DomCanvasElement shrunk2 = getDisplayCanvas(surface); + final DomHTMLCanvasElement shrunk2 = getDisplayCanvas(surface); canvasSize = getCssSize(surface); expect(shrunk2, same(huge)); @@ -182,7 +182,7 @@ void testMain() { // This tests https://github.com/flutter/flutter/issues/77084 EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(2.0); surface.createOrUpdateSurface(const BitmapSize(5, 15)); - final DomCanvasElement dpr2Canvas = getDisplayCanvas(surface); + final DomHTMLCanvasElement dpr2Canvas = getDisplayCanvas(surface); canvasSize = getCssSize(surface); expect(dpr2Canvas, same(huge)); @@ -363,15 +363,15 @@ void testMain() { }); } -DomCanvasElement getDisplayCanvas(Surface surface) { +DomHTMLCanvasElement getDisplayCanvas(Surface surface) { assert(surface.isDisplayCanvas); - return surface.hostElement.children.first as DomCanvasElement; + return surface.hostElement.children.first as DomHTMLCanvasElement; } /// Extracts the CSS style values of 'width' and 'height' and returns them /// as a [ui.Size]. ui.Size getCssSize(Surface surface) { - final DomCanvasElement canvas = getDisplayCanvas(surface); + final DomHTMLCanvasElement canvas = getDisplayCanvas(surface); final String cssWidth = canvas.style.width; final String cssHeight = canvas.style.height; // CSS width and height should be in the form 'NNNpx'. So cut off the 'px' and diff --git a/engine/src/flutter/lib/web_ui/test/common/matchers.dart b/engine/src/flutter/lib/web_ui/test/common/matchers.dart index e12d1a90251..b04e6b87d2e 100644 --- a/engine/src/flutter/lib/web_ui/test/common/matchers.dart +++ b/engine/src/flutter/lib/web_ui/test/common/matchers.dart @@ -5,6 +5,7 @@ /// Provides utilities for testing engine code. library matchers; +import 'dart:js_interop'; import 'dart:math' as math; import 'package:html/dom.dart' as html; @@ -259,14 +260,19 @@ class HtmlPatternMatcher extends Matcher { @override bool matches(final Object? object, Map matchState) { - if (object is! DomElement) { + // TODO(srujzs): Replace this with `!object.isJSAny` once we have that API + // in `dart:js_interop`. + // https://github.com/dart-lang/sdk/issues/56905 + // ignore: invalid_runtime_check_with_js_interop_types + if (object is! JSAny || !object.isA()) { return false; } final List mismatches = []; matchState['mismatches'] = mismatches; - final html.Element element = html.parseFragment(object.outerHTML).children.single; + final html.Element element = + html.parseFragment((object as DomElement).outerHTML).children.single; matchElements(_Breadcrumbs.root, mismatches, element, pattern); return mismatches.isEmpty; } diff --git a/engine/src/flutter/lib/web_ui/test/engine/configuration_test.dart b/engine/src/flutter/lib/web_ui/test/engine/configuration_test.dart index ebfc250917f..808f19973a4 100644 --- a/engine/src/flutter/lib/web_ui/test/engine/configuration_test.dart +++ b/engine/src/flutter/lib/web_ui/test/engine/configuration_test.dart @@ -5,7 +5,7 @@ @TestOn('browser') library; -import 'package:js/js_util.dart' as js_util; +import 'dart:js_interop'; import 'package:test/bootstrap/browser.dart'; import 'package:test/test.dart'; @@ -27,7 +27,7 @@ void testMain() { test('legacy constructor initializes with a Js Object', () async { final FlutterConfiguration config = FlutterConfiguration.legacy( - js_util.jsify({'canvasKitBaseUrl': '/some_other_url/'}) + {'canvasKitBaseUrl': '/some_other_url/'}.jsify()! as JsFlutterConfiguration, ); @@ -38,13 +38,13 @@ void testMain() { group('setUserConfiguration', () { test('throws assertion error if already initialized from JS', () async { final FlutterConfiguration config = FlutterConfiguration.legacy( - js_util.jsify({'canvasKitBaseUrl': '/some_other_url/'}) + {'canvasKitBaseUrl': '/some_other_url/'}.jsify()! as JsFlutterConfiguration, ); expect(() { config.setUserConfiguration( - js_util.jsify({'canvasKitBaseUrl': '/yet_another_url/'}) + {'canvasKitBaseUrl': '/yet_another_url/'}.jsify()! as JsFlutterConfiguration, ); }, throwsAssertionError); @@ -54,8 +54,7 @@ void testMain() { final FlutterConfiguration config = FlutterConfiguration.legacy(null); config.setUserConfiguration( - js_util.jsify({'canvasKitBaseUrl': '/one_more_url/'}) - as JsFlutterConfiguration, + {'canvasKitBaseUrl': '/one_more_url/'}.jsify()! as JsFlutterConfiguration, ); expect(config.canvasKitBaseUrl, '/one_more_url/'); @@ -66,7 +65,7 @@ void testMain() { expect(() { config.setUserConfiguration( - js_util.jsify({'nonexistentProperty': 32.0}) as JsFlutterConfiguration, + {'nonexistentProperty': 32.0}.jsify()! as JsFlutterConfiguration, ); }, returnsNormally); }); @@ -76,9 +75,7 @@ void testMain() { late FlutterConfiguration defaultConfig; setUp(() { defaultConfig = FlutterConfiguration(); - defaultConfig.setUserConfiguration( - js_util.jsify({}) as JsFlutterConfiguration, - ); + defaultConfig.setUserConfiguration({}.jsify()! as JsFlutterConfiguration); }); test('canvasKitVariant', () { @@ -96,7 +93,7 @@ void testMain() { final FlutterConfiguration config = FlutterConfiguration(); config.setUserConfiguration( // With an empty map, the canvasKitVariant is undefined in JS. - js_util.jsify({}) as JsFlutterConfiguration, + {}.jsify()! as JsFlutterConfiguration, ); expect(config.canvasKitVariant, CanvasKitVariant.auto); @@ -106,23 +103,22 @@ void testMain() { final FlutterConfiguration config = FlutterConfiguration(); config.setUserConfiguration( - js_util.jsify({'canvasKitVariant': 'foo'}) as JsFlutterConfiguration, + {'canvasKitVariant': 'foo'}.jsify()! as JsFlutterConfiguration, ); expect(() => config.canvasKitVariant, throwsArgumentError); config.setUserConfiguration( - js_util.jsify({'canvasKitVariant': 'auto'}) as JsFlutterConfiguration, + {'canvasKitVariant': 'auto'}.jsify()! as JsFlutterConfiguration, ); expect(config.canvasKitVariant, CanvasKitVariant.auto); config.setUserConfiguration( - js_util.jsify({'canvasKitVariant': 'full'}) as JsFlutterConfiguration, + {'canvasKitVariant': 'full'}.jsify()! as JsFlutterConfiguration, ); expect(config.canvasKitVariant, CanvasKitVariant.full); config.setUserConfiguration( - js_util.jsify({'canvasKitVariant': 'chromium'}) - as JsFlutterConfiguration, + {'canvasKitVariant': 'chromium'}.jsify()! as JsFlutterConfiguration, ); expect(config.canvasKitVariant, CanvasKitVariant.chromium); }); @@ -131,7 +127,7 @@ void testMain() { test('multiViewEnabled', () { final FlutterConfiguration config = FlutterConfiguration(); config.setUserConfiguration( - js_util.jsify({'multiViewEnabled': true}) as JsFlutterConfiguration, + {'multiViewEnabled': true}.jsify()! as JsFlutterConfiguration, ); expect(config.multiViewEnabled, isTrue); }); diff --git a/engine/src/flutter/lib/web_ui/test/engine/dom_http_fetch_test.dart b/engine/src/flutter/lib/web_ui/test/engine/dom_http_fetch_test.dart index 41d6cb4db1a..b906bb21857 100644 --- a/engine/src/flutter/lib/web_ui/test/engine/dom_http_fetch_test.dart +++ b/engine/src/flutter/lib/web_ui/test/engine/dom_http_fetch_test.dart @@ -93,7 +93,7 @@ Future _testSuccessfulPayloads() async { expect(response.hasPayload, isTrue); expect(response.payload, isNotNull); expect(response.url, '/test_images/'); - expect(await response.json(), isA>()); + expect(((await response.json()) as JSAny?).isA(), isTrue); }); test('httpFetch reads data in chunks', () async { @@ -119,9 +119,7 @@ Future _testSuccessfulPayloads() async { expect(response.url, url); final List result = []; - await response.payload.read( - (JSUint8Array chunk) => result.addAll(chunk.toDart), - ); + await response.payload.read((JSUint8Array chunk) => result.addAll(chunk.toDart)); expect(result, hasLength(length)); expect(result, List.generate(length, (int i) => i & 0xFF)); } @@ -154,7 +152,7 @@ Future _testSuccessfulPayloads() async { test('httpFetchJson fetches json', () async { final Object? json = await httpFetchJson('/test_images/'); - expect(json, isA>()); + expect((json as JSAny?).isA(), isTrue); }); } diff --git a/engine/src/flutter/lib/web_ui/test/engine/image_format_detector_test.dart b/engine/src/flutter/lib/web_ui/test/engine/image_format_detector_test.dart index 552229cb547..8507522c1bf 100644 --- a/engine/src/flutter/lib/web_ui/test/engine/image_format_detector_test.dart +++ b/engine/src/flutter/lib/web_ui/test/engine/image_format_detector_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 'dart:typed_data'; import 'package:test/bootstrap/browser.dart'; @@ -21,7 +22,8 @@ Future testMain() async { Future> createTestFiles() async { final HttpFetchResponse listingResponse = await httpFetch('/test_images/'); - List testFiles = (await listingResponse.json() as List).cast(); + List testFiles = + ((await listingResponse.json() as JSAny?).dartify()! as List).cast(); testFiles = testFiles.map((String baseName) => '/test_images/$baseName').toList(); // Sanity-check the test file list. If suddenly test files are moved or diff --git a/engine/src/flutter/lib/web_ui/test/engine/pointer_binding_test.dart b/engine/src/flutter/lib/web_ui/test/engine/pointer_binding_test.dart index 6568d60f852..4b84468a7bf 100644 --- a/engine/src/flutter/lib/web_ui/test/engine/pointer_binding_test.dart +++ b/engine/src/flutter/lib/web_ui/test/engine/pointer_binding_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 'dart:js_util' as js_util; import 'package:meta/meta.dart'; @@ -83,7 +84,7 @@ void testMain() { test('_PointerEventContext generates expected events', () { DomPointerEvent expectCorrectType(DomEvent e) { - expect(domInstanceOfString(e, 'PointerEvent'), isTrue); + expect(e.isA(), isTrue); return e as DomPointerEvent; } @@ -2526,7 +2527,7 @@ void testMain() { Listener.register( event: 'custom-event', target: eventTarget, - handler: (event) { + handler: (DomEvent event) { expect(event, expected); handled = true; }, @@ -2541,7 +2542,7 @@ void testMain() { final Listener listener = Listener.register( event: 'custom-event', target: eventTarget, - handler: (event) { + handler: (DomEvent event) { handled = true; }, ); diff --git a/engine/src/flutter/lib/web_ui/test/engine/routing_test.dart b/engine/src/flutter/lib/web_ui/test/engine/routing_test.dart index 04e82893ae9..eb0afd8ed48 100644 --- a/engine/src/flutter/lib/web_ui/test/engine/routing_test.dart +++ b/engine/src/flutter/lib/web_ui/test/engine/routing_test.dart @@ -9,6 +9,7 @@ import 'package:test/test.dart'; import 'package:ui/src/engine.dart' hide window; import 'package:ui/ui.dart' as ui; import 'package:ui/ui_web/src/ui_web.dart' as ui_web; +import 'package:ui/ui_web/src/ui_web/navigation/url_strategy.dart'; import '../common/matchers.dart'; import '../common/test_initialization.dart'; @@ -507,7 +508,7 @@ class _SampleUrlStrategy implements ui_web.UrlStrategy { Object? getState() => _state; @override - ui.VoidCallback addPopStateListener(DartDomEventListener listener) { + ui.VoidCallback addPopStateListener(PopStateListener listener) { wasUsed = true; return () {}; } diff --git a/engine/src/flutter/lib/web_ui/test/engine/scene_view_test.dart b/engine/src/flutter/lib/web_ui/test/engine/scene_view_test.dart index 03602b0af7a..cd548708c13 100644 --- a/engine/src/flutter/lib/web_ui/test/engine/scene_view_test.dart +++ b/engine/src/flutter/lib/web_ui/test/engine/scene_view_test.dart @@ -3,7 +3,6 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:js_interop'; import 'dart:typed_data'; import 'package:test/bootstrap/browser.dart'; @@ -21,7 +20,7 @@ void main() { } class StubPictureRenderer implements PictureRenderer { - final DomCanvasElement scratchCanvasElement = createDomCanvasElement(width: 500, height: 500); + final DomHTMLCanvasElement scratchCanvasElement = createDomCanvasElement(width: 500, height: 500); @override Future renderPictures(List pictures) async { @@ -29,7 +28,7 @@ class StubPictureRenderer implements PictureRenderer { final List bitmaps = await Future.wait( pictures.map((ScenePicture picture) { final ui.Rect cullRect = picture.cullRect; - final Future bitmap = createImageBitmap(scratchCanvasElement as JSObject, ( + final Future bitmap = createImageBitmap(scratchCanvasElement, ( x: 0, y: 0, width: cullRect.width.toInt(), diff --git a/engine/src/flutter/lib/web_ui/test/engine/semantics/semantics_test.dart b/engine/src/flutter/lib/web_ui/test/engine/semantics/semantics_test.dart index 983982f3b5a..32ae0a392ed 100644 --- a/engine/src/flutter/lib/web_ui/test/engine/semantics/semantics_test.dart +++ b/engine/src/flutter/lib/web_ui/test/engine/semantics/semantics_test.dart @@ -1582,7 +1582,7 @@ void _testVerticalScrolling() { final scrollable = owner().debugSemanticsTree![0]!.semanticRole! as SemanticScrollable; final scrollEvent = createDomEvent('Event', 'scroll') as JSAny; - final listener = scrollable.scrollListener! as JSFunction; + final listener = scrollable.scrollListener!; expect(() => listener.callAsFunction(null, scrollEvent), returnsNormally); semantics().semanticsEnabled = false; diff --git a/engine/src/flutter/lib/web_ui/test/engine/text_editing_test.dart b/engine/src/flutter/lib/web_ui/test/engine/text_editing_test.dart index 3ca4d0c0634..a6370f48cc3 100644 --- a/engine/src/flutter/lib/web_ui/test/engine/text_editing_test.dart +++ b/engine/src/flutter/lib/web_ui/test/engine/text_editing_test.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'dart:async'; +import 'dart:js_interop'; import 'dart:js_util' as js_util; import 'dart:typed_data'; @@ -1151,7 +1152,9 @@ Future testMain() async { test('Moves the focus across input elements', () async { final List focusinEvents = []; - final DomEventListener handleFocusIn = createDomEventListener(focusinEvents.add); + final DomEventListener handleFocusIn = createDomEventListener((DomEvent event) { + focusinEvents.add(event); + }); final MethodCall setClient1 = MethodCall('TextInput.setClient', [ 123, @@ -3640,8 +3643,8 @@ void cleanTestFlags() { void checkInputEditingState(DomElement? element, String text, int start, int end) { expect(element, isNotNull); - expect(domInstanceOfString(element, 'HTMLInputElement'), true); - final DomHTMLInputElement input = element! as DomHTMLInputElement; + expect(element!.isA(), true); + final DomHTMLInputElement input = element as DomHTMLInputElement; expect(defaultTextEditingRoot.ownerDocument?.activeElement, input); expect(input.value, text); expect(input.selectionStart, start); diff --git a/engine/src/flutter/lib/web_ui/test/engine/view_embedder/dom_manager_test.dart b/engine/src/flutter/lib/web_ui/test/engine/view_embedder/dom_manager_test.dart index 6de075326fe..09893a9c3c2 100644 --- a/engine/src/flutter/lib/web_ui/test/engine/view_embedder/dom_manager_test.dart +++ b/engine/src/flutter/lib/web_ui/test/engine/view_embedder/dom_manager_test.dart @@ -103,7 +103,7 @@ void doTests() { test('Initializes and attaches a shadow root', () { final DomManager domManager = DomManager(devicePixelRatio: 3.0); - expect(domInstanceOfString(domManager.renderingHost, 'ShadowRoot'), isTrue); + expect(domManager.renderingHost.isA(), isTrue); expect(domManager.renderingHost.host, domManager.platformViewsHost); expect(domManager.renderingHost, domManager.platformViewsHost.shadowRoot); diff --git a/engine/src/flutter/lib/web_ui/test/engine/view_embedder/flutter_views_proxy_test.dart b/engine/src/flutter/lib/web_ui/test/engine/view_embedder/flutter_views_proxy_test.dart index 7a369744dd5..b640f32802d 100644 --- a/engine/src/flutter/lib/web_ui/test/engine/view_embedder/flutter_views_proxy_test.dart +++ b/engine/src/flutter/lib/web_ui/test/engine/view_embedder/flutter_views_proxy_test.dart @@ -106,12 +106,7 @@ Future doTests() async { } // The JS-interop definition of the `initialData` object passed to the views of this app. -@JS() -@staticInterop -class InitialData {} - -/// The attributes of the [InitialData] object. -extension InitialDataExtension on InitialData { +extension type InitialData._(JSObject _) implements JSObject { external int get someInt; external String? get someString; diff --git a/engine/src/flutter/lib/web_ui/test/fallbacks/fallbacks_test.dart b/engine/src/flutter/lib/web_ui/test/fallbacks/fallbacks_test.dart index 7ebfbc0de81..5f2a3cc64e3 100644 --- a/engine/src/flutter/lib/web_ui/test/fallbacks/fallbacks_test.dart +++ b/engine/src/flutter/lib/web_ui/test/fallbacks/fallbacks_test.dart @@ -17,7 +17,7 @@ void main() { } @JS() -external JSBoolean get crossOriginIsolated; +external bool get crossOriginIsolated; Future testMain() async { setUpUnitTests(setUpTestViewDimensions: false); @@ -27,7 +27,7 @@ Future testMain() async { expect(isWasm, isTrue); expect(isSkwasm, isTrue); final bool shouldBeMultiThreaded = - crossOriginIsolated.toDart && !configuration.forceSingleThreadedSkwasm; + crossOriginIsolated && !configuration.forceSingleThreadedSkwasm; expect(isMultiThreaded, shouldBeMultiThreaded); } else { expect(isWasm, isFalse); diff --git a/engine/src/flutter/lib/web_ui/test/ui/image/html_image_element_codec_test.dart b/engine/src/flutter/lib/web_ui/test/ui/image/html_image_element_codec_test.dart index b69ca781eaa..e3230a0f964 100644 --- a/engine/src/flutter/lib/web_ui/test/ui/image/html_image_element_codec_test.dart +++ b/engine/src/flutter/lib/web_ui/test/ui/image/html_image_element_codec_test.dart @@ -8,7 +8,6 @@ import 'dart:typed_data'; import 'package:test/bootstrap/browser.dart'; import 'package:test/test.dart'; import 'package:ui/src/engine/canvaskit/image.dart'; -import 'package:ui/src/engine/dom.dart'; import 'package:ui/src/engine/html_image_element_codec.dart'; import 'package:ui/ui.dart' as ui; import 'package:ui/ui_web/src/ui_web.dart' as ui_web; diff --git a/engine/src/flutter/lib/web_ui/test/ui/image_golden_test.dart b/engine/src/flutter/lib/web_ui/test/ui/image_golden_test.dart index ef5ddbdfcb7..38063cde230 100644 --- a/engine/src/flutter/lib/web_ui/test/ui/image_golden_test.dart +++ b/engine/src/flutter/lib/web_ui/test/ui/image_golden_test.dart @@ -4,7 +4,6 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:js_interop'; import 'dart:math'; import 'dart:typed_data'; @@ -422,18 +421,18 @@ Future testMain() async { image.src = url; await completer.future; - final DomImageBitmap bitmap = await createImageBitmap(image as JSObject); + final DomImageBitmap bitmap = await createImageBitmap(image); domWindow.URL.revokeObjectURL(url); - expect(bitmap.width.toDartInt, 150); - expect(bitmap.height.toDartInt, 150); + expect(bitmap.width, 150); + expect(bitmap.height, 150); final ui.Image uiImage = await renderer.createImageFromImageBitmap(bitmap); if (isSkwasm && isMultiThreaded) { // Multi-threaded skwasm transfers the bitmap to the web worker, so it should be // disposed/consumed. - expect(bitmap.width.toDartInt, 0); - expect(bitmap.height.toDartInt, 0); + expect(bitmap.width, 0); + expect(bitmap.height, 0); } return uiImage; }); diff --git a/engine/src/flutter/web_sdk/sdk_rewriter.dart b/engine/src/flutter/web_sdk/sdk_rewriter.dart index 94e73333b12..b60dd6d0b06 100644 --- a/engine/src/flutter/web_sdk/sdk_rewriter.dart +++ b/engine/src/flutter/web_sdk/sdk_rewriter.dart @@ -62,8 +62,7 @@ import 'dart:collection'; import 'dart:convert' hide Codec; import 'dart:developer' as developer; import 'dart:js_util' as js_util; -import 'dart:_js_annotations'; -import 'dart:js_interop' hide JS; +import 'dart:js_interop'; import 'dart:js_interop_unsafe'; import 'dart:math' as math; import 'dart:typed_data'; diff --git a/engine/src/flutter/web_sdk/test/js_access_test.dart b/engine/src/flutter/web_sdk/test/js_access_test.dart index 12f88845def..bc77f3323db 100644 --- a/engine/src/flutter/web_sdk/test/js_access_test.dart +++ b/engine/src/flutter/web_sdk/test/js_access_test.dart @@ -17,7 +17,7 @@ import 'dart:io'; import 'package:test/test.dart'; // Libraries that allow making arbitrary calls to JavaScript. -const List _jsAccessLibraries = ['dart:js_util', 'package:js']; +const List _jsAccessLibraries = ['dart:js_util']; // Libraries that are allowed to make direct calls to JavaScript. These // libraries must be reviewed carefully to make sure JavaScript APIs are used diff --git a/engine/src/flutter/web_sdk/test/sdk_rewriter_test.dart b/engine/src/flutter/web_sdk/test/sdk_rewriter_test.dart index 6a03a42217d..55e92cba4b4 100644 --- a/engine/src/flutter/web_sdk/test/sdk_rewriter_test.dart +++ b/engine/src/flutter/web_sdk/test/sdk_rewriter_test.dart @@ -31,8 +31,7 @@ import 'dart:collection'; import 'dart:convert' hide Codec; import 'dart:developer' as developer; import 'dart:js_util' as js_util; -import 'dart:_js_annotations'; -import 'dart:js_interop' hide JS; +import 'dart:js_interop'; import 'dart:js_interop_unsafe'; import 'dart:math' as math; import 'dart:typed_data'; @@ -70,8 +69,7 @@ import 'dart:collection'; import 'dart:convert' hide Codec; import 'dart:developer' as developer; import 'dart:js_util' as js_util; -import 'dart:_js_annotations'; -import 'dart:js_interop' hide JS; +import 'dart:js_interop'; import 'dart:js_interop_unsafe'; import 'dart:math' as math; import 'dart:typed_data'; diff --git a/engine/src/flutter/web_sdk/web_engine_tester/lib/static/host.dart b/engine/src/flutter/web_sdk/web_engine_tester/lib/static/host.dart index 04874b83484..c515ed7360d 100644 --- a/engine/src/flutter/web_sdk/web_engine_tester/lib/static/host.dart +++ b/engine/src/flutter/web_sdk/web_engine_tester/lib/static/host.dart @@ -4,9 +4,6 @@ // ignore_for_file: avoid_dynamic_calls -@JS() -library test.host; - import 'dart:async'; import 'dart:convert'; import 'dart:js_interop'; @@ -17,30 +14,21 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:ui/src/engine/dom.dart'; /// A class defined in content shell, used to control its behavior. -@JS() -@staticInterop -class _TestRunner {} - -extension _TestRunnerExtension on _TestRunner { - external JSVoid waitUntilDone(); +extension type _TestRunner(JSObject _) implements JSObject { + external void waitUntilDone(); } /// Returns the current content shell runner, or `null` if none exists. -@JS() +@JS('testRunner') external _TestRunner? get testRunner; // ignore: library_private_types_in_public_api /// A class that exposes the test API to JS. /// /// These are exposed so that tools like IDEs can interact with them via remote /// debugging. -@JS() -@anonymous -@staticInterop -class _JSApi { - external factory _JSApi({JSFunction resume, JSFunction restartCurrent}); -} +extension type _JSApi._(JSObject _) implements JSObject { + external _JSApi({JSFunction resume, JSFunction restartCurrent}); -extension _JSApiExtension on _JSApi { /// Causes the test runner to resume running, as though the user had clicked /// the "play" button. // ignore: unused_element @@ -225,52 +213,68 @@ StreamChannel _connectToIframe(String url, int id) { _domSubscriptions[id] = domSubscriptions; _streamSubscriptions[id] = streamSubscriptions; domSubscriptions.add( - DomSubscription(domWindow, 'message', (DomEvent event) { - final DomMessageEvent message = event as DomMessageEvent; - // A message on the Window can theoretically come from any website. It's - // very unlikely that a malicious site would care about hacking someone's - // unit tests, let alone be able to find the test server while it's - // running, but it's good practice to check the origin anyway. - if (message.origin != domWindow.location.origin) { - return; - } - if (message.source.location?.href != iframe.src) { - return; - } + DomSubscription( + domWindow, + 'message', + createDomEventListener((DomEvent event) { + final DomMessageEvent message = event as DomMessageEvent; + // A message on the Window can theoretically come from any website. It's + // very unlikely that a malicious site would care about hacking someone's + // unit tests, let alone be able to find the test server while it's + // running, but it's good practice to check the origin anyway. + if (message.origin != domWindow.location.origin) { + return; + } + // We have to do these ugly casts because the message is cross-origin + // which isn't handled cleanly by dart:js_interop. + if (((message.source as DomMessageEventSource?)?.location as DomMessageEventLocation?) + ?.href != + iframe.src) { + return; + } - message.stopPropagation(); + message.stopPropagation(); - if (message.data == 'port') { - final DomMessagePort port = message.ports.first; - domSubscriptions.add( - DomSubscription(port, 'message', (DomEvent event) { - controller.local.sink.add((event as DomMessageEvent).data); - }), - ); - port.start(); - streamSubscriptions.add(controller.local.stream.listen(port.postMessage)); - } else if (message.data['ready'] == true) { - // This message indicates that the iframe is actively listening for - // events, so the message channel's second port can now be transferred. - final DomMessageChannel channel = createDomMessageChannel(); - channel.port1.start(); - channel.port2.start(); - iframe.contentWindow.postMessage('port', domWindow.location.origin, [ - channel.port2, - ]); - domSubscriptions.add( - DomSubscription(channel.port1, 'message', (DomEvent message) { - controller.local.sink.add((message as DomMessageEvent).data['data']); - }), - ); + if (message.data == 'port') { + final DomMessagePort port = message.ports[0]; + domSubscriptions.add( + DomSubscription( + port, + 'message', + createDomEventListener((DomEvent event) { + controller.local.sink.add((event as DomMessageEvent).data); + }), + ), + ); + port.start(); + streamSubscriptions.add(controller.local.stream.listen(port.postMessage)); + } else if (message.data['ready'] == true) { + // This message indicates that the iframe is actively listening for + // events, so the message channel's second port can now be transferred. + final DomMessageChannel channel = createDomMessageChannel(); + channel.port1.start(); + channel.port2.start(); + iframe.contentWindow.postMessage('port', domWindow.location.origin, [ + channel.port2, + ]); + domSubscriptions.add( + DomSubscription( + channel.port1, + 'message', + createDomEventListener((DomEvent message) { + controller.local.sink.add((message as DomMessageEvent).data['data']); + }), + ), + ); - streamSubscriptions.add(controller.local.stream.listen(channel.port1.postMessage)); - } else if (message.data['exception'] == true) { - // This message from `dart.js` indicates that an exception occurred - // loading the test. - controller.local.sink.add(message.data['data']); - } - }), + streamSubscriptions.add(controller.local.stream.listen(channel.port1.postMessage)); + } else if (message.data['exception'] == true) { + // This message from `dart.js` indicates that an exception occurred + // loading the test. + controller.local.sink.add(message.data['data']); + } + }), + ), ); return controller.foreign;