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

Commit 8274f54

Browse files
Reverts "Reland "Output .js files as ES6 modules. (#52023)" (#53688)" (#53709)
Reverts: #53688 Initiated by: jiahaog Reason for reverting: canvaskit.js cannot be loaded in an internal end to end test - see b/350885206 Original PR Author: eyebrowsoffire Reviewed By: {ditman} This change reverts the following previous change: This is an attempt to reland #52023. The issue previously is that if it was not specified by the user, the default CanvasKit base URL did not have a leading slash, which does not work when doing dynamic imports.
1 parent 44e1d0b commit 8274f54

File tree

8 files changed

+118
-61
lines changed

8 files changed

+118
-61
lines changed

DEPS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ allowed_hosts = [
277277
]
278278

279279
deps = {
280-
'src': 'https://github.com/flutter/buildroot.git' + '@' + 'e265c359126b24351f534080fb22edaa159f2215',
280+
'src': 'https://github.com/flutter/buildroot.git' + '@' + '8c2d66fa4e6298894425f5bdd0591bc5b1154c53',
281281

282282
'src/flutter/third_party/depot_tools':
283283
Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '580b4ff3f5cd0dcaa2eacda28cefe0f45320e8f7',

lib/web_ui/flutter_js/src/canvaskit_loader.js

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import { createWasmInstantiator } from "./instantiate_wasm.js";
66
import { joinPathSegments } from "./utils.js";
77

88
export const loadCanvasKit = (deps, config, browserEnvironment, canvasKitBaseUrl) => {
9-
window.flutterCanvasKitLoaded = (async () => {
10-
if (window.flutterCanvasKit) {
11-
// The user has set this global variable ahead of time, so we just return that.
12-
return window.flutterCanvasKit;
13-
}
9+
if (window.flutterCanvasKit) {
10+
// The user has set this global variable ahead of time, so we just return that.
11+
return Promise.resolve(window.flutterCanvasKit);
12+
}
13+
window.flutterCanvasKitLoaded = new Promise((resolve, reject) => {
1414
const supportsChromiumCanvasKit = browserEnvironment.hasChromiumBreakIterators && browserEnvironment.hasImageCodecs;
1515
if (!supportsChromiumCanvasKit && config.canvasKitVariant == "chromium") {
1616
throw "Chromium CanvasKit variant specifically requested, but unsupported in this browser";
@@ -25,11 +25,24 @@ export const loadCanvasKit = (deps, config, browserEnvironment, canvasKitBaseUrl
2525
canvasKitUrl = deps.flutterTT.policy.createScriptURL(canvasKitUrl);
2626
}
2727
const wasmInstantiator = createWasmInstantiator(joinPathSegments(baseUrl, "canvaskit.wasm"));
28-
const canvasKitModule = await import(canvasKitUrl);
29-
window.flutterCanvasKit = await canvasKitModule.default({
30-
instantiateWasm: wasmInstantiator,
28+
const script = document.createElement("script");
29+
script.src = canvasKitUrl;
30+
if (config.nonce) {
31+
script.nonce = config.nonce;
32+
}
33+
script.addEventListener("load", async () => {
34+
try {
35+
const canvasKit = await CanvasKitInit({
36+
instantiateWasm: wasmInstantiator,
37+
});
38+
window.flutterCanvasKit = canvasKit;
39+
resolve(canvasKit);
40+
} catch (e) {
41+
reject(e);
42+
}
3143
});
32-
return window.flutterCanvasKit;
33-
})();
44+
script.addEventListener("error", reject);
45+
document.head.appendChild(script);
46+
});
3447
return window.flutterCanvasKitLoaded;
3548
}

lib/web_ui/flutter_js/src/skwasm_loader.js

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,43 @@
55
import { createWasmInstantiator } from "./instantiate_wasm.js";
66
import { joinPathSegments } from "./utils.js";
77

8-
export const loadSkwasm = async (deps, config, browserEnvironment, baseUrl) => {
9-
let skwasmUrl = joinPathSegments(baseUrl, "skwasm.js");
10-
if (deps.flutterTT.policy) {
11-
skwasmUrl = deps.flutterTT.policy.createScriptURL(skwasmUrl);
12-
}
13-
const wasmInstantiator = createWasmInstantiator(joinPathSegments(baseUrl, "skwasm.wasm"));
14-
const skwasm = await import(skwasmUrl);
15-
return await skwasm.default({
16-
instantiateWasm: wasmInstantiator,
17-
locateFile: (fileName, scriptDirectory) => {
18-
// When hosted via a CDN or some other url that is not the same
19-
// origin as the main script of the page, we will fail to create
20-
// a web worker with the .worker.js script. This workaround will
21-
// make sure that the worker JS can be loaded regardless of where
22-
// it is hosted.
23-
const url = scriptDirectory + fileName;
24-
if (url.endsWith('.worker.js')) {
25-
return URL.createObjectURL(new Blob(
26-
[`importScripts('${url}');`],
27-
{ 'type': 'application/javascript' }));
28-
}
29-
return url;
8+
export const loadSkwasm = (deps, config, browserEnvironment, baseUrl) => {
9+
return new Promise((resolve, reject) => {
10+
let skwasmUrl = joinPathSegments(baseUrl, "skwasm.js");
11+
if (deps.flutterTT.policy) {
12+
skwasmUrl = deps.flutterTT.policy.createScriptURL(skwasmUrl);
13+
}
14+
const wasmInstantiator = createWasmInstantiator(joinPathSegments(baseUrl, "skwasm.wasm"));
15+
const script = document.createElement("script");
16+
script.src = skwasmUrl;
17+
if (config.nonce) {
18+
script.nonce = config.nonce;
3019
}
20+
script.addEventListener("load", async () => {
21+
try {
22+
const skwasmInstance = await skwasm({
23+
instantiateWasm: wasmInstantiator,
24+
locateFile: (fileName, scriptDirectory) => {
25+
// When hosted via a CDN or some other url that is not the same
26+
// origin as the main script of the page, we will fail to create
27+
// a web worker with the .worker.js script. This workaround will
28+
// make sure that the worker JS can be loaded regardless of where
29+
// it is hosted.
30+
const url = scriptDirectory + fileName;
31+
if (url.endsWith(".worker.js")) {
32+
return URL.createObjectURL(new Blob(
33+
[`importScripts("${url}");`],
34+
{ "type": "application/javascript" }));
35+
}
36+
return url;
37+
}
38+
});
39+
resolve(skwasmInstance);
40+
} catch (e) {
41+
reject(e);
42+
}
43+
});
44+
script.addEventListener("error", reject);
45+
document.head.appendChild(script);
3146
});
3247
}

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

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -259,13 +259,12 @@ extension CanvasKitExtension on CanvasKit {
259259
);
260260
}
261261

262-
@JS()
263-
@staticInterop
264-
class CanvasKitModule {}
262+
@JS('window.CanvasKitInit')
263+
external JSAny _CanvasKitInit(CanvasKitInitOptions options);
265264

266-
extension CanvasKitModuleExtension on CanvasKitModule {
267-
@JS('default')
268-
external JSPromise<JSAny> defaultExport(CanvasKitInitOptions options);
265+
Future<CanvasKit> CanvasKitInit(CanvasKitInitOptions options) {
266+
return js_util.promiseToFuture<CanvasKit>(
267+
_CanvasKitInit(options).toObjectShallow);
269268
}
270269

271270
typedef LocateFileCallback = String Function(String file, String unusedBase);
@@ -3662,11 +3661,11 @@ String canvasKitWasmModuleUrl(String file, String canvasKitBase) =>
36623661
/// Downloads the CanvasKit JavaScript, then calls `CanvasKitInit` to download
36633662
/// and intialize the CanvasKit wasm.
36643663
Future<CanvasKit> downloadCanvasKit() async {
3665-
final CanvasKitModule canvasKitModule = await _downloadOneOf(_canvasKitJsUrls);
3664+
await _downloadOneOf(_canvasKitJsUrls);
36663665

3667-
final CanvasKit canvasKit = (await canvasKitModule.defaultExport(CanvasKitInitOptions(
3666+
final CanvasKit canvasKit = await CanvasKitInit(CanvasKitInitOptions(
36683667
locateFile: createLocateFileCallback(canvasKitWasmModuleUrl),
3669-
)).toDart) as CanvasKit;
3668+
));
36703669

36713670
if (canvasKit.ParagraphBuilder.RequiresClientICU() && !browserSupportsCanvaskitChromium) {
36723671
throw Exception(
@@ -3682,12 +3681,10 @@ Future<CanvasKit> downloadCanvasKit() async {
36823681
/// downloads it.
36833682
///
36843683
/// If none of the URLs can be downloaded, throws an [Exception].
3685-
Future<CanvasKitModule> _downloadOneOf(Iterable<String> urls) async {
3684+
Future<void> _downloadOneOf(Iterable<String> urls) async {
36863685
for (final String url in urls) {
3687-
try {
3688-
return await _downloadCanvasKitJs(url);
3689-
} catch (_) {
3690-
continue;
3686+
if (await _downloadCanvasKitJs(url)) {
3687+
return;
36913688
}
36923689
}
36933690

@@ -3701,7 +3698,32 @@ Future<CanvasKitModule> _downloadOneOf(Iterable<String> urls) async {
37013698
///
37023699
/// Returns a [Future] that completes with `true` if the CanvasKit JavaScript
37033700
/// file was successfully downloaded, or `false` if it failed.
3704-
Future<CanvasKitModule> _downloadCanvasKitJs(String url) async {
3705-
final JSAny scriptUrl = createTrustedScriptUrl(url);
3706-
return (await importModule(scriptUrl).toDart) as CanvasKitModule;
3701+
Future<bool> _downloadCanvasKitJs(String url) {
3702+
final DomHTMLScriptElement canvasKitScript =
3703+
createDomHTMLScriptElement(configuration.nonce);
3704+
canvasKitScript.src = createTrustedScriptUrl(url);
3705+
3706+
final Completer<bool> canvasKitLoadCompleter = Completer<bool>();
3707+
3708+
late final DomEventListener loadCallback;
3709+
late final DomEventListener errorCallback;
3710+
3711+
void loadEventHandler(DomEvent _) {
3712+
canvasKitScript.remove();
3713+
canvasKitLoadCompleter.complete(true);
3714+
}
3715+
void errorEventHandler(DomEvent errorEvent) {
3716+
canvasKitScript.remove();
3717+
canvasKitLoadCompleter.complete(false);
3718+
}
3719+
3720+
loadCallback = createDomEventListener(loadEventHandler);
3721+
errorCallback = createDomEventListener(errorEventHandler);
3722+
3723+
canvasKitScript.addEventListener('load', loadCallback);
3724+
canvasKitScript.addEventListener('error', errorCallback);
3725+
3726+
domDocument.head!.appendChild(canvasKitScript);
3727+
3728+
return canvasKitLoadCompleter.future;
37073729
}

lib/web_ui/lib/src/engine/configuration.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ class FlutterConfiguration {
241241
_configuration?.canvasKitBaseUrl ?? _defaultCanvasKitBaseUrl;
242242
static const String _defaultCanvasKitBaseUrl = String.fromEnvironment(
243243
'FLUTTER_WEB_CANVASKIT_URL',
244-
defaultValue: '/canvaskit/',
244+
defaultValue: 'canvaskit/',
245245
);
246246

247247
/// The variant of CanvasKit to download.

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3383,16 +3383,16 @@ final DomTrustedTypePolicy _ttPolicy = domWindow.trustedTypes!.createPolicy(
33833383

33843384
/// Converts a String `url` into a [DomTrustedScriptURL] object when the
33853385
/// Trusted Types API is available, else returns the unmodified `url`.
3386-
JSAny createTrustedScriptUrl(String url) {
3386+
Object createTrustedScriptUrl(String url) {
33873387
if (domWindow.trustedTypes != null) {
33883388
// Pass `url` through Flutter Engine's TrustedType policy.
33893389
final DomTrustedScriptURL trustedUrl = _ttPolicy.createScriptURL(url);
33903390

33913391
assert(trustedUrl.url != '', 'URL: $url rejected by TrustedTypePolicy');
33923392

3393-
return trustedUrl as JSAny;
3393+
return trustedUrl;
33943394
}
3395-
return url.toJS;
3395+
return url;
33963396
}
33973397

33983398
DomMessageChannel createDomMessageChannel() => DomMessageChannel();

lib/web_ui/test/canvaskit/initialization/does_not_mock_module_exports_test.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ void testMain() {
1818
// Initialize CanvasKit...
1919
await bootstrapAndRunApp();
2020

21+
// CanvasKitInit should be defined...
22+
expect(
23+
js_util.hasProperty(domWindow, 'CanvasKitInit'),
24+
isTrue,
25+
reason: 'CanvasKitInit should be defined on Window',
26+
);
27+
2128
// window.exports and window.module should be undefined!
2229
expect(
2330
js_util.hasProperty(domWindow, 'exports'),

lib/web_ui/test/engine/configuration_test.dart

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,30 +22,30 @@ void testMain() {
2222
test('initializes with null', () async {
2323
final FlutterConfiguration config = FlutterConfiguration.legacy(null);
2424

25-
expect(config.canvasKitBaseUrl, '/canvaskit/'); // _defaultCanvasKitBaseUrl
25+
expect(config.canvasKitBaseUrl, 'canvaskit/'); // _defaultCanvasKitBaseUrl
2626
});
2727

2828
test('legacy constructor initializes with a Js Object', () async {
2929
final FlutterConfiguration config = FlutterConfiguration.legacy(
3030
js_util.jsify(<String, Object?>{
31-
'canvasKitBaseUrl': '/some_other_url/',
31+
'canvasKitBaseUrl': 'some_other_url/',
3232
}) as JsFlutterConfiguration);
3333

34-
expect(config.canvasKitBaseUrl, '/some_other_url/');
34+
expect(config.canvasKitBaseUrl, 'some_other_url/');
3535
});
3636
});
3737

3838
group('setUserConfiguration', () {
3939
test('throws assertion error if already initialized from JS', () async {
4040
final FlutterConfiguration config = FlutterConfiguration.legacy(
4141
js_util.jsify(<String, Object?>{
42-
'canvasKitBaseUrl': '/some_other_url/',
42+
'canvasKitBaseUrl': 'some_other_url/',
4343
}) as JsFlutterConfiguration);
4444

4545
expect(() {
4646
config.setUserConfiguration(
4747
js_util.jsify(<String, Object?>{
48-
'canvasKitBaseUrl': '/yet_another_url/',
48+
'canvasKitBaseUrl': 'yet_another_url/',
4949
}) as JsFlutterConfiguration);
5050
}, throwsAssertionError);
5151
});
@@ -55,10 +55,10 @@ void testMain() {
5555

5656
config.setUserConfiguration(
5757
js_util.jsify(<String, Object?>{
58-
'canvasKitBaseUrl': '/one_more_url/',
58+
'canvasKitBaseUrl': 'one_more_url/',
5959
}) as JsFlutterConfiguration);
6060

61-
expect(config.canvasKitBaseUrl, '/one_more_url/');
61+
expect(config.canvasKitBaseUrl, 'one_more_url/');
6262
});
6363

6464
test('can receive non-existing properties without crashing', () async {

0 commit comments

Comments
 (0)