Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 9460ad7

Browse files
committed
[web] Migrate Flutter Web DOM usage to JS static interop - 3.
1 parent b5e7336 commit 9460ad7

File tree

3 files changed

+79
-12
lines changed

3 files changed

+79
-12
lines changed

lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import 'dart:typed_data';
2020
import 'package:js/js.dart';
2121
import 'package:ui/ui.dart' as ui;
2222

23+
import '../dom.dart';
2324
import '../profiler.dart';
2425

2526
/// Entrypoint into the CanvasKit API.
@@ -2332,7 +2333,7 @@ class ProductionCollector implements Collector {
23322333
/// emptied out to prevent memory leaks. This may happen, for example, when the
23332334
/// same object is deleted more than once.
23342335
void collectSkiaObjectsNow() {
2335-
html.window.performance.mark('SkObject collection-start');
2336+
domWindow.performance.mark('SkObject collection-start');
23362337
final int length = _skiaObjectCollectionQueue.length;
23372338
dynamic firstError;
23382339
StackTrace? firstStackTrace;
@@ -2364,8 +2365,8 @@ class ProductionCollector implements Collector {
23642365
}
23652366
_skiaObjectCollectionQueue = <SkDeletable>[];
23662367

2367-
html.window.performance.mark('SkObject collection-end');
2368-
html.window.performance.measure('SkObject collection',
2368+
domWindow.performance.mark('SkObject collection-end');
2369+
domWindow.performance.measure('SkObject collection',
23692370
'SkObject collection-start', 'SkObject collection-end');
23702371

23712372
// It's safe to throw the error here, now that we've processed the queue.
@@ -2539,14 +2540,14 @@ extension SkPartialImageInfoExtension on SkPartialImageInfo {
25392540
// TODO(hterkelsen): Rather than this monkey-patch hack, we should
25402541
// build CanvasKit ourselves. See:
25412542
// https://github.com/flutter/flutter/issues/52588
2542-
void patchCanvasKitModule(html.ScriptElement canvasKitScript) {
2543+
void patchCanvasKitModule(DomHTMLScriptElement canvasKitScript) {
25432544
// First check if `exports` and `module` are already defined. If so, then
25442545
// CommonJS is being used, and we shouldn't have any problems.
25452546
final js.JsFunction objectConstructor = js.context['Object'] as js.JsFunction;
25462547
if (js.context['exports'] == null) {
25472548
final js.JsObject exportsAccessor = js.JsObject.jsify(<String, dynamic>{
25482549
'get': allowInterop(() {
2549-
if (html.document.currentScript == canvasKitScript) {
2550+
if (domDocument.currentScript == canvasKitScript) {
25502551
return js.JsObject(objectConstructor);
25512552
} else {
25522553
return js.context['_flutterWebCachedExports'];
@@ -2563,7 +2564,7 @@ void patchCanvasKitModule(html.ScriptElement canvasKitScript) {
25632564
if (js.context['module'] == null) {
25642565
final js.JsObject moduleAccessor = js.JsObject.jsify(<String, dynamic>{
25652566
'get': allowInterop(() {
2566-
if (html.document.currentScript == canvasKitScript) {
2567+
if (domDocument.currentScript == canvasKitScript) {
25672568
return js.JsObject(objectConstructor);
25682569
} else {
25692570
return js.context['_flutterWebCachedModule'];
@@ -2577,5 +2578,5 @@ void patchCanvasKitModule(html.ScriptElement canvasKitScript) {
25772578
objectConstructor.callMethod(
25782579
'defineProperty', <dynamic>[js.context, 'module', moduleAccessor]);
25792580
}
2580-
html.document.head!.append(canvasKitScript);
2581+
domDocument.head!.appendChild(canvasKitScript);
25812582
}

lib/web_ui/lib/src/engine/canvaskit/initialization.dart

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'dart:html' as html;
99
import '../../engine.dart' show kProfileMode;
1010
import '../browser_detection.dart';
1111
import '../configuration.dart';
12+
import '../dom.dart';
1213
import '../safe_browser_api.dart';
1314
import 'canvaskit_api.dart';
1415
import 'fonts.dart';
@@ -91,15 +92,17 @@ Future<void> _downloadCanvasKitJs({String? canvasKitBase}) {
9192
? canvasKitBase + 'canvaskit.js'
9293
: canvasKitJavaScriptBindingsUrl;
9394

94-
final html.ScriptElement canvasKitScript = html.ScriptElement();
95+
final DomHTMLScriptElement canvasKitScript = createDomHTMLScriptElement();
9596
canvasKitScript.src = canvasKitJavaScriptUrl;
9697

9798
final Completer<void> canvasKitLoadCompleter = Completer<void>();
98-
late StreamSubscription<html.Event> loadSubscription;
99-
loadSubscription = canvasKitScript.onLoad.listen((_) {
100-
loadSubscription.cancel();
99+
late DomEventListener callback;
100+
void loadEventHandler(DomEvent _) {
101101
canvasKitLoadCompleter.complete();
102-
});
102+
canvasKitScript.removeEventListener('load', callback);
103+
}
104+
callback = allowInterop(loadEventHandler);
105+
canvasKitScript.addEventListener('load', callback);
103106

104107
patchCanvasKitModule(canvasKitScript);
105108

lib/web_ui/lib/src/engine/dom.dart

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class DomWindow {}
2121
extension DomWindowExtension on DomWindow {
2222
external DomDocument get document;
2323
external DomNavigator get navigator;
24+
external DomPerformance get performance;
2425
}
2526

2627
@JS('window')
@@ -44,16 +45,45 @@ class DomDocument {}
4445
extension DomDocumentExtension on DomDocument {
4546
external /* List<Node> */ List<Object?> querySelectorAll(String selectors);
4647
external DomElement createElement(String name, [dynamic options]);
48+
external DomHTMLScriptElement? get currentScript;
4749
}
4850

51+
@JS()
52+
@staticInterop
53+
class DomHTMLDocument extends DomDocument {}
54+
55+
extension DomHTMLDocumentExtension on DomHTMLDocument {
56+
external DomHTMLHeadElement? get head;
57+
}
58+
59+
@JS('document')
60+
external DomHTMLDocument get domDocument;
61+
4962
@JS()
5063
@staticInterop
5164
class DomEventTarget {}
5265

66+
extension DomEventTargetExtension on DomEventTarget {
67+
external void addEventListener(String type, DomEventListener? listener,
68+
[bool? useCapture]);
69+
external void removeEventListener(String type, DomEventListener? listener,
70+
[bool? useCapture]);
71+
}
72+
73+
typedef DomEventListener = void Function(DomEvent event);
74+
75+
@JS()
76+
@staticInterop
77+
class DomEvent {}
78+
5379
@JS()
5480
@staticInterop
5581
class DomNode extends DomEventTarget {}
5682

83+
extension DomNodeExtension on DomNode {
84+
external DomNode appendChild(DomNode node);
85+
}
86+
5787
@JS()
5888
@staticInterop
5989
class DomElement extends DomNode {}
@@ -72,6 +102,39 @@ extension DomHTMLMetaElementExtension on DomHTMLMetaElement {
72102
external String get content;
73103
}
74104

105+
@JS()
106+
@staticInterop
107+
class DomHTMLHeadElement extends DomHTMLElement {}
108+
109+
@JS()
110+
@staticInterop
111+
class DomHTMLScriptElement extends DomHTMLElement {}
112+
113+
extension DomHTMLScriptElementExtension on DomHTMLScriptElement {
114+
external set src(String value);
115+
}
116+
117+
DomHTMLScriptElement createDomHTMLScriptElement() =>
118+
domDocument.createElement('script') as DomHTMLScriptElement;
119+
120+
@JS()
121+
@staticInterop
122+
class DomPerformance extends DomEventTarget {}
123+
124+
extension DomPerformanceExtension on DomPerformance {
125+
external DomPerformanceEntry? mark(String markName);
126+
external DomPerformanceMeasure? measure(
127+
String measureName, String? startMark, String? endMark);
128+
}
129+
130+
@JS()
131+
@staticInterop
132+
class DomPerformanceEntry {}
133+
134+
@JS()
135+
@staticInterop
136+
class DomPerformanceMeasure extends DomPerformanceEntry {}
137+
75138
@JS()
76139
@staticInterop
77140
class DomCanvasElement extends DomHTMLElement {}

0 commit comments

Comments
 (0)