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

Commit e890901

Browse files
author
Harry Terkelsen
authored
Don't register CanvasKit with define (#22745)
1 parent 8832b48 commit e890901

File tree

1 file changed

+92
-23
lines changed

1 file changed

+92
-23
lines changed

lib/web_ui/lib/src/engine/dom_renderer.dart

Lines changed: 92 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ class DomRenderer {
7878
/// This getter calls the `hasFocus` method of the `Document` interface.
7979
/// See for more details:
8080
/// https://developer.mozilla.org/en-US/docs/Web/API/Document/hasFocus
81-
bool? get windowHasFocus => js_util.callMethod(html.document, 'hasFocus', <dynamic>[]);
81+
bool? get windowHasFocus =>
82+
js_util.callMethod(html.document, 'hasFocus', <dynamic>[]);
8283

8384
void _setupHotRestart() {
8485
// This persists across hot restarts to clear stale DOM.
@@ -172,7 +173,8 @@ class DomRenderer {
172173
js_util.setProperty(element, name, value);
173174
}
174175

175-
static void setElementStyle(html.Element element, String name, String? value) {
176+
static void setElementStyle(
177+
html.Element element, String name, String? value) {
176178
if (value == null) {
177179
element.style.removeProperty(name);
178180
} else {
@@ -181,8 +183,8 @@ class DomRenderer {
181183
}
182184

183185
static void setElementTransform(html.Element element, String transformValue) {
184-
js_util.setProperty(js_util.getProperty(element, 'style'), 'transform',
185-
transformValue);
186+
js_util.setProperty(
187+
js_util.getProperty(element, 'style'), 'transform', transformValue);
186188
}
187189

188190
void setText(html.Element element, String text) {
@@ -200,7 +202,8 @@ class DomRenderer {
200202
}
201203

202204
void setThemeColor(ui.Color color) {
203-
html.MetaElement? theme = html.document.querySelector('#flutterweb-theme') as html.MetaElement?;
205+
html.MetaElement? theme =
206+
html.document.querySelector('#flutterweb-theme') as html.MetaElement?;
204207
if (theme == null) {
205208
theme = html.MetaElement()
206209
..id = 'flutterweb-theme'
@@ -315,8 +318,8 @@ flt-glass-pane * {
315318
// This css prevents an autofill overlay brought by the browser during
316319
// text field autofill by delaying the transition effect.
317320
// See: https://github.com/flutter/flutter/issues/61132.
318-
if(browserHasAutofillOverlay()) {
319-
sheet.insertRule('''
321+
if (browserHasAutofillOverlay()) {
322+
sheet.insertRule('''
320323
.transparentTextEditing:-webkit-autofill,
321324
.transparentTextEditing:-webkit-autofill:hover,
322325
.transparentTextEditing:-webkit-autofill:focus,
@@ -326,7 +329,6 @@ flt-glass-pane * {
326329
''', sheet.cssRules.length);
327330
}
328331

329-
330332
final html.BodyElement bodyElement = html.document.body!;
331333
setElementStyle(bodyElement, 'position', 'fixed');
332334
setElementStyle(bodyElement, 'top', '0');
@@ -416,8 +418,7 @@ flt-glass-pane * {
416418
// pointer events through to the semantics tree. However, for platform
417419
// views, the pointer events will not pass through, and will be handled
418420
// by the platform view.
419-
glassPaneElement
420-
.insertBefore(_accesibilityPlaceholder, _sceneHostElement);
421+
glassPaneElement.insertBefore(_accesibilityPlaceholder, _sceneHostElement);
421422

422423
PointerBinding.initInstance(glassPaneElement);
423424

@@ -460,6 +461,66 @@ flt-glass-pane * {
460461
_canvasKitScript?.remove();
461462
_canvasKitScript = html.ScriptElement();
462463
_canvasKitScript!.src = canvasKitBaseUrl + 'canvaskit.js';
464+
465+
// TODO(hterkelsen): Rather than this monkey-patch hack, we should
466+
// build CanvasKit ourselves. See:
467+
// https://github.com/flutter/flutter/issues/52588
468+
469+
// Monkey-patch the top-level `module` and `exports` objects so that
470+
// CanvasKit doesn't attempt to register itself as an anonymous module.
471+
//
472+
// The idea behind making these fake `exports` and `module` objects is
473+
// that `canvaskit.js` contains the following lines of code:
474+
//
475+
// if (typeof exports === 'object' && typeof module === 'object')
476+
// module.exports = CanvasKitInit;
477+
// else if (typeof define === 'function' && define['amd'])
478+
// define([], function() { return CanvasKitInit; });
479+
//
480+
// We need to avoid hitting the case where CanvasKit defines an anonymous
481+
// module, since this breaks RequireJS, which DDC and some plugins use.
482+
// Temporarily removing the `define` function won't work because RequireJS
483+
// could load in between this code running and the CanvasKit code running.
484+
// Also, we cannot monkey-patch the `define` function because it is
485+
// non-configurable (it is a top-level 'var').
486+
487+
// First check if `exports` and `module` are already defined. If so, then
488+
// CommonJS is being used, and we shouldn't have any problems.
489+
js.JsFunction objectConstructor = js.context['Object'];
490+
if (js.context['exports'] == null) {
491+
js.JsObject exportsAccessor = js.JsObject.jsify({
492+
'get': js.allowInterop(() {
493+
if (html.document.currentScript == _canvasKitScript) {
494+
return js.JsObject(objectConstructor);
495+
} else {
496+
return js.context['_flutterWebCachedExports'];
497+
}
498+
}),
499+
'set': js.allowInterop((dynamic value) {
500+
js.context['_flutterWebCachedExports'] = value;
501+
}),
502+
'configurable': true,
503+
});
504+
objectConstructor.callMethod('defineProperty',
505+
<dynamic>[js.context, 'exports', exportsAccessor]);
506+
}
507+
if (js.context['module'] == null) {
508+
js.JsObject moduleAccessor = js.JsObject.jsify({
509+
'get': js.allowInterop(() {
510+
if (html.document.currentScript == _canvasKitScript) {
511+
return js.JsObject(objectConstructor);
512+
} else {
513+
return js.context['_flutterWebCachedModule'];
514+
}
515+
}),
516+
'set': js.allowInterop((dynamic value) {
517+
js.context['_flutterWebCachedModule'] = value;
518+
}),
519+
'configurable': true,
520+
});
521+
objectConstructor.callMethod(
522+
'defineProperty', <dynamic>[js.context, 'module', moduleAccessor]);
523+
}
463524
html.document.head!.append(_canvasKitScript!);
464525
}
465526

@@ -469,8 +530,8 @@ flt-glass-pane * {
469530
} else {
470531
_resizeSubscription = html.window.onResize.listen(_metricsDidChange);
471532
}
472-
_localeSubscription = languageChangeEvent.forTarget(html.window)
473-
.listen(_languageDidChange);
533+
_localeSubscription =
534+
languageChangeEvent.forTarget(html.window).listen(_languageDidChange);
474535
EnginePlatformDispatcher.instance._updateLocales();
475536
}
476537

@@ -484,7 +545,7 @@ flt-glass-pane * {
484545
/// Note: always check for rotations for a mobile device. Update the physical
485546
/// size if the change is caused by a rotation.
486547
void _metricsDidChange(html.Event? event) {
487-
if(isMobile && !window.isRotation() && textEditing.isEditing) {
548+
if (isMobile && !window.isRotation() && textEditing.isEditing) {
488549
window.computeOnScreenKeyboardInsets();
489550
EnginePlatformDispatcher.instance.invokeOnMetricsChanged();
490551
} else {
@@ -517,13 +578,20 @@ flt-glass-pane * {
517578
static bool? _ellipseFeatureDetected;
518579

519580
/// Draws CanvasElement ellipse with fallback.
520-
static void ellipse(html.CanvasRenderingContext2D context,
521-
double centerX, double centerY, double radiusX, double radiusY,
522-
double rotation, double startAngle, double endAngle, bool antiClockwise) {
581+
static void ellipse(
582+
html.CanvasRenderingContext2D context,
583+
double centerX,
584+
double centerY,
585+
double radiusX,
586+
double radiusY,
587+
double rotation,
588+
double startAngle,
589+
double endAngle,
590+
bool antiClockwise) {
523591
_ellipseFeatureDetected ??= js_util.getProperty(context, 'ellipse') != null;
524592
if (_ellipseFeatureDetected!) {
525-
context.ellipse(centerX, centerY, radiusX, radiusY,
526-
rotation, startAngle, endAngle, antiClockwise);
593+
context.ellipse(centerX, centerY, radiusX, radiusY, rotation, startAngle,
594+
endAngle, antiClockwise);
527595
} else {
528596
context.save();
529597
context.translate(centerX, centerY);
@@ -539,9 +607,11 @@ flt-glass-pane * {
539607
static const String orientationLockTypeLandscape = 'landscape';
540608
static const String orientationLockTypePortrait = 'portrait';
541609
static const String orientationLockTypePortraitPrimary = 'portrait-primary';
542-
static const String orientationLockTypePortraitSecondary = 'portrait-secondary';
610+
static const String orientationLockTypePortraitSecondary =
611+
'portrait-secondary';
543612
static const String orientationLockTypeLandscapePrimary = 'landscape-primary';
544-
static const String orientationLockTypeLandscapeSecondary = 'landscape-secondary';
613+
static const String orientationLockTypeLandscapeSecondary =
614+
'landscape-secondary';
545615

546616
/// Sets preferred screen orientation.
547617
///
@@ -556,8 +626,7 @@ flt-glass-pane * {
556626
Future<bool> setPreferredOrientation(List<dynamic>? orientations) {
557627
final html.Screen screen = html.window.screen!;
558628
if (!_unsafeIsNull(screen)) {
559-
final html.ScreenOrientation? screenOrientation =
560-
screen.orientation;
629+
final html.ScreenOrientation? screenOrientation = screen.orientation;
561630
if (!_unsafeIsNull(screenOrientation)) {
562631
if (orientations!.isEmpty) {
563632
screenOrientation!.unlock();
@@ -588,7 +657,7 @@ flt-glass-pane * {
588657

589658
// Converts device orientation to w3c OrientationLockType enum.
590659
static String? _deviceOrientationToLockType(String deviceOrientation) {
591-
switch(deviceOrientation) {
660+
switch (deviceOrientation) {
592661
case 'DeviceOrientation.portraitUp':
593662
return orientationLockTypePortraitPrimary;
594663
case 'DeviceOrientation.landscapeLeft':

0 commit comments

Comments
 (0)