diff --git a/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart b/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart index b512eedef8328..234b0e67fb796 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart @@ -20,6 +20,7 @@ import 'dart:typed_data'; import 'package:js/js.dart'; import 'package:ui/ui.dart' as ui; +import '../dom.dart'; import '../profiler.dart'; /// Entrypoint into the CanvasKit API. @@ -2332,7 +2333,7 @@ class ProductionCollector implements Collector { /// emptied out to prevent memory leaks. This may happen, for example, when the /// same object is deleted more than once. void collectSkiaObjectsNow() { - html.window.performance.mark('SkObject collection-start'); + domWindow.performance.mark('SkObject collection-start'); final int length = _skiaObjectCollectionQueue.length; dynamic firstError; StackTrace? firstStackTrace; @@ -2364,8 +2365,8 @@ class ProductionCollector implements Collector { } _skiaObjectCollectionQueue = []; - html.window.performance.mark('SkObject collection-end'); - html.window.performance.measure('SkObject collection', + domWindow.performance.mark('SkObject collection-end'); + domWindow.performance.measure('SkObject collection', 'SkObject collection-start', 'SkObject collection-end'); // It's safe to throw the error here, now that we've processed the queue. @@ -2539,14 +2540,14 @@ extension SkPartialImageInfoExtension on SkPartialImageInfo { // TODO(hterkelsen): Rather than this monkey-patch hack, we should // build CanvasKit ourselves. See: // https://github.com/flutter/flutter/issues/52588 -void patchCanvasKitModule(html.ScriptElement canvasKitScript) { +void patchCanvasKitModule(DomHTMLScriptElement canvasKitScript) { // First check if `exports` and `module` are already defined. If so, then // CommonJS is being used, and we shouldn't have any problems. final js.JsFunction objectConstructor = js.context['Object'] as js.JsFunction; if (js.context['exports'] == null) { final js.JsObject exportsAccessor = js.JsObject.jsify({ 'get': allowInterop(() { - if (html.document.currentScript == canvasKitScript) { + if (domDocument.currentScript == canvasKitScript) { return js.JsObject(objectConstructor); } else { return js.context['_flutterWebCachedExports']; @@ -2563,7 +2564,7 @@ void patchCanvasKitModule(html.ScriptElement canvasKitScript) { if (js.context['module'] == null) { final js.JsObject moduleAccessor = js.JsObject.jsify({ 'get': allowInterop(() { - if (html.document.currentScript == canvasKitScript) { + if (domDocument.currentScript == canvasKitScript) { return js.JsObject(objectConstructor); } else { return js.context['_flutterWebCachedModule']; @@ -2577,5 +2578,5 @@ void patchCanvasKitModule(html.ScriptElement canvasKitScript) { objectConstructor.callMethod( 'defineProperty', [js.context, 'module', moduleAccessor]); } - html.document.head!.append(canvasKitScript); + domDocument.head!.appendChild(canvasKitScript); } diff --git a/lib/web_ui/lib/src/engine/canvaskit/initialization.dart b/lib/web_ui/lib/src/engine/canvaskit/initialization.dart index 4bad1c89f31b7..8fdc698de30c9 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/initialization.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/initialization.dart @@ -9,6 +9,7 @@ import 'dart:html' as html; import '../../engine.dart' show kProfileMode; import '../browser_detection.dart'; import '../configuration.dart'; +import '../dom.dart'; import '../safe_browser_api.dart'; import 'canvaskit_api.dart'; import 'fonts.dart'; @@ -91,15 +92,17 @@ Future _downloadCanvasKitJs({String? canvasKitBase}) { ? canvasKitBase + 'canvaskit.js' : canvasKitJavaScriptBindingsUrl; - final html.ScriptElement canvasKitScript = html.ScriptElement(); + final DomHTMLScriptElement canvasKitScript = createDomHTMLScriptElement(); canvasKitScript.src = canvasKitJavaScriptUrl; final Completer canvasKitLoadCompleter = Completer(); - late StreamSubscription loadSubscription; - loadSubscription = canvasKitScript.onLoad.listen((_) { - loadSubscription.cancel(); + late DomEventListener callback; + void loadEventHandler(DomEvent _) { canvasKitLoadCompleter.complete(); - }); + canvasKitScript.removeEventListener('load', callback); + } + callback = allowInterop(loadEventHandler); + canvasKitScript.addEventListener('load', callback); patchCanvasKitModule(canvasKitScript); diff --git a/lib/web_ui/lib/src/engine/dom.dart b/lib/web_ui/lib/src/engine/dom.dart index 1d5bcfc0f5977..bfac75196ac1b 100644 --- a/lib/web_ui/lib/src/engine/dom.dart +++ b/lib/web_ui/lib/src/engine/dom.dart @@ -21,6 +21,7 @@ class DomWindow {} extension DomWindowExtension on DomWindow { external DomDocument get document; external DomNavigator get navigator; + external DomPerformance get performance; } @JS('window') @@ -44,16 +45,45 @@ class DomDocument {} extension DomDocumentExtension on DomDocument { external /* List */ List querySelectorAll(String selectors); external DomElement createElement(String name, [dynamic options]); + external DomHTMLScriptElement? get currentScript; } +@JS() +@staticInterop +class DomHTMLDocument extends DomDocument {} + +extension DomHTMLDocumentExtension on DomHTMLDocument { + external DomHTMLHeadElement? get head; +} + +@JS('document') +external DomHTMLDocument get domDocument; + @JS() @staticInterop class DomEventTarget {} +extension DomEventTargetExtension on DomEventTarget { + external void addEventListener(String type, DomEventListener? listener, + [bool? useCapture]); + external void removeEventListener(String type, DomEventListener? listener, + [bool? useCapture]); +} + +typedef DomEventListener = void Function(DomEvent event); + +@JS() +@staticInterop +class DomEvent {} + @JS() @staticInterop class DomNode extends DomEventTarget {} +extension DomNodeExtension on DomNode { + external DomNode appendChild(DomNode node); +} + @JS() @staticInterop class DomElement extends DomNode {} @@ -72,6 +102,39 @@ extension DomHTMLMetaElementExtension on DomHTMLMetaElement { external String get content; } +@JS() +@staticInterop +class DomHTMLHeadElement extends DomHTMLElement {} + +@JS() +@staticInterop +class DomHTMLScriptElement extends DomHTMLElement {} + +extension DomHTMLScriptElementExtension on DomHTMLScriptElement { + external set src(String value); +} + +DomHTMLScriptElement createDomHTMLScriptElement() => + domDocument.createElement('script') as DomHTMLScriptElement; + +@JS() +@staticInterop +class DomPerformance extends DomEventTarget {} + +extension DomPerformanceExtension on DomPerformance { + external DomPerformanceEntry? mark(String markName); + external DomPerformanceMeasure? measure( + String measureName, String? startMark, String? endMark); +} + +@JS() +@staticInterop +class DomPerformanceEntry {} + +@JS() +@staticInterop +class DomPerformanceMeasure extends DomPerformanceEntry {} + @JS() @staticInterop class DomCanvasElement extends DomHTMLElement {}