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

Commit abee142

Browse files
Fixes a few issues in flutter_js (#53231)
This addresses a couple things: flutter/flutter#147610 (Treat `auto` renderer properly) flutter/flutter#149443 (Add an entrypoint base url config option) This also adds a `useLocalCanvasKit` configuration option on the build config, which the flutter tool can use to fix flutter/flutter#148713
1 parent 9633a3b commit abee142

File tree

11 files changed

+112
-49
lines changed

11 files changed

+112
-49
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42761,7 +42761,6 @@ ORIGIN: ../../../flutter/lib/ui/window/pointer_data_packet_converter.cc + ../../
4276142761
ORIGIN: ../../../flutter/lib/ui/window/pointer_data_packet_converter.h + ../../../flutter/LICENSE
4276242762
ORIGIN: ../../../flutter/lib/ui/window/viewport_metrics.cc + ../../../flutter/LICENSE
4276342763
ORIGIN: ../../../flutter/lib/ui/window/viewport_metrics.h + ../../../flutter/LICENSE
42764-
ORIGIN: ../../../flutter/lib/web_ui/flutter_js/src/base_uri.js + ../../../flutter/LICENSE
4276542764
ORIGIN: ../../../flutter/lib/web_ui/flutter_js/src/browser_environment.js + ../../../flutter/LICENSE
4276642765
ORIGIN: ../../../flutter/lib/web_ui/flutter_js/src/canvaskit_loader.js + ../../../flutter/LICENSE
4276742766
ORIGIN: ../../../flutter/lib/web_ui/flutter_js/src/entrypoint_loader.js + ../../../flutter/LICENSE
@@ -42771,6 +42770,7 @@ ORIGIN: ../../../flutter/lib/web_ui/flutter_js/src/loader.js + ../../../flutter/
4277142770
ORIGIN: ../../../flutter/lib/web_ui/flutter_js/src/service_worker_loader.js + ../../../flutter/LICENSE
4277242771
ORIGIN: ../../../flutter/lib/web_ui/flutter_js/src/skwasm_loader.js + ../../../flutter/LICENSE
4277342772
ORIGIN: ../../../flutter/lib/web_ui/flutter_js/src/trusted_types.js + ../../../flutter/LICENSE
42773+
ORIGIN: ../../../flutter/lib/web_ui/flutter_js/src/utils.js + ../../../flutter/LICENSE
4277442774
ORIGIN: ../../../flutter/lib/web_ui/lib/annotations.dart + ../../../flutter/LICENSE
4277542775
ORIGIN: ../../../flutter/lib/web_ui/lib/canvas.dart + ../../../flutter/LICENSE
4277642776
ORIGIN: ../../../flutter/lib/web_ui/lib/channel_buffers.dart + ../../../flutter/LICENSE
@@ -45632,7 +45632,6 @@ FILE: ../../../flutter/lib/ui/window/pointer_data_packet_converter.cc
4563245632
FILE: ../../../flutter/lib/ui/window/pointer_data_packet_converter.h
4563345633
FILE: ../../../flutter/lib/ui/window/viewport_metrics.cc
4563445634
FILE: ../../../flutter/lib/ui/window/viewport_metrics.h
45635-
FILE: ../../../flutter/lib/web_ui/flutter_js/src/base_uri.js
4563645635
FILE: ../../../flutter/lib/web_ui/flutter_js/src/browser_environment.js
4563745636
FILE: ../../../flutter/lib/web_ui/flutter_js/src/canvaskit_loader.js
4563845637
FILE: ../../../flutter/lib/web_ui/flutter_js/src/entrypoint_loader.js
@@ -45643,6 +45642,7 @@ FILE: ../../../flutter/lib/web_ui/flutter_js/src/service_worker_loader.js
4564345642
FILE: ../../../flutter/lib/web_ui/flutter_js/src/skwasm_loader.js
4564445643
FILE: ../../../flutter/lib/web_ui/flutter_js/src/trusted_types.js
4564545644
FILE: ../../../flutter/lib/web_ui/flutter_js/src/types.d.ts
45645+
FILE: ../../../flutter/lib/web_ui/flutter_js/src/utils.js
4564645646
FILE: ../../../flutter/lib/web_ui/lib/annotations.dart
4564745647
FILE: ../../../flutter/lib/web_ui/lib/canvas.dart
4564845648
FILE: ../../../flutter/lib/web_ui/lib/channel_buffers.dart

lib/web_ui/dev/test_platform.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,7 @@ class BrowserPlatform extends PlatformPlugin {
562562
</script>
563563
<script>
564564
_flutter.buildConfig = {
565+
useLocalCanvaskit: true,
565566
builds: [
566567
$buildConfigsString
567568
]
@@ -571,7 +572,6 @@ class BrowserPlatform extends PlatformPlugin {
571572
<script>
572573
_flutter.loader.load({
573574
config: {
574-
canvasKitBaseUrl: "/canvaskit/",
575575
// Some of our tests rely on color emoji
576576
useColorEmoji: true,
577577
canvasKitVariant: "${getCanvasKitVariant()}",

lib/web_ui/flutter_js/sources.gni

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
# found in the LICENSE file.
44

55
flutter_js_source_list = [
6-
"src/base_uri.js",
76
"src/browser_environment.js",
87
"src/canvaskit_loader.js",
98
"src/entrypoint_loader.js",
@@ -13,6 +12,7 @@ flutter_js_source_list = [
1312
"src/service_worker_loader.js",
1413
"src/skwasm_loader.js",
1514
"src/trusted_types.js",
15+
"src/utils.js",
1616

1717
"src/types.d.ts",
1818
]

lib/web_ui/flutter_js/src/base_uri.js

Lines changed: 0 additions & 17 deletions
This file was deleted.

lib/web_ui/flutter_js/src/canvaskit_loader.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
// found in the LICENSE file.
44

55
import { createWasmInstantiator } from "./instantiate_wasm.js";
6+
import { joinPathSegments } from "./utils.js";
67

7-
export const loadCanvasKit = (deps, config, browserEnvironment, engineRevision) => {
8+
export const loadCanvasKit = (deps, config, browserEnvironment, canvasKitBaseUrl) => {
89
if (window.flutterCanvasKit) {
910
// The user has set this global variable ahead of time, so we just return that.
1011
return Promise.resolve(window.flutterCanvasKit);
@@ -15,21 +16,21 @@ export const loadCanvasKit = (deps, config, browserEnvironment, engineRevision)
1516
throw "Chromium CanvasKit variant specifically requested, but unsupported in this browser";
1617
}
1718
const useChromiumCanvasKit = supportsChromiumCanvasKit && (config.canvasKitVariant !== "full");
18-
let baseUrl = config.canvasKitBaseUrl ?? `https://www.gstatic.com/flutter-canvaskit/${engineRevision}/`;
19+
let baseUrl = canvasKitBaseUrl;
1920
if (useChromiumCanvasKit) {
20-
baseUrl = `${baseUrl}chromium/`;
21+
baseUrl = joinPathSegments(baseUrl, "chromium");
2122
}
22-
let canvasKitUrl = `${baseUrl}canvaskit.js`;
23+
let canvasKitUrl = joinPathSegments(baseUrl, "canvaskit.js");
2324
if (deps.flutterTT.policy) {
2425
canvasKitUrl = deps.flutterTT.policy.createScriptURL(canvasKitUrl);
2526
}
26-
const wasmInstantiator = createWasmInstantiator(`${baseUrl}canvaskit.wasm`);
27+
const wasmInstantiator = createWasmInstantiator(joinPathSegments(baseUrl, "canvaskit.wasm"));
2728
const script = document.createElement("script");
2829
script.src = canvasKitUrl;
2930
if (config.nonce) {
3031
script.nonce = config.nonce;
3132
}
32-
script.addEventListener('load', async () => {
33+
script.addEventListener("load", async () => {
3334
try {
3435
const canvasKit = await CanvasKitInit({
3536
instantiateWasm: wasmInstantiator,
@@ -40,7 +41,7 @@ export const loadCanvasKit = (deps, config, browserEnvironment, engineRevision)
4041
reject(e);
4142
}
4243
});
43-
script.addEventListener('error', reject);
44+
script.addEventListener("error", reject);
4445
document.head.appendChild(script);
4546
});
4647
return window.flutterCanvasKitLoaded;

lib/web_ui/flutter_js/src/entrypoint_loader.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
import { baseUri } from "./base_uri.js";
5+
import { baseUri, joinPathSegments } from "./utils.js";
66

77
/**
88
* Handles injecting the main Flutter web entrypoint (main.dart.js), and notifying
@@ -37,7 +37,7 @@ export class FlutterEntrypointLoader {
3737
* Returns undefined when an `onEntrypointLoaded` callback is supplied in `options`.
3838
*/
3939
async loadEntrypoint(options) {
40-
const { entrypointUrl = `${baseUri}main.dart.js`, onEntrypointLoaded, nonce } =
40+
const { entrypointUrl = joinPathSegments(baseUri, "main.dart.js"), onEntrypointLoaded, nonce } =
4141
options || {};
4242
return this._loadJSEntrypoint(entrypointUrl, onEntrypointLoaded, nonce);
4343
}
@@ -63,11 +63,12 @@ export class FlutterEntrypointLoader {
6363
onEntrypointLoaded ??= (engineInitializer) => {
6464
engineInitializer.initializeEngine(config).then((appRunner) => appRunner.runApp())
6565
};
66+
const { entryPointBaseUrl } = config;
6667
if (build.compileTarget === "dart2wasm") {
67-
return this._loadWasmEntrypoint(build, deps, onEntrypointLoaded);
68+
return this._loadWasmEntrypoint(build, deps, entryPointBaseUrl, onEntrypointLoaded);
6869
} else {
6970
const mainPath = build.mainJsPath ?? "main.dart.js";
70-
const entrypointUrl = `${baseUri}${mainPath}`;
71+
const entrypointUrl = joinPathSegments(baseUri, entryPointBaseUrl, mainPath);
7172
return this._loadJSEntrypoint(entrypointUrl, onEntrypointLoaded, nonce);
7273
}
7374
}
@@ -138,16 +139,17 @@ export class FlutterEntrypointLoader {
138139
*
139140
* @param {import("./types").WasmApplicationBuild} build
140141
* @param {*} deps
142+
* @param {string} entryPointBaseUrl
141143
* @param {import("./types").OnEntrypointLoadedCallback} onEntrypointLoaded
142144
*/
143-
async _loadWasmEntrypoint(build, deps, onEntrypointLoaded) {
145+
async _loadWasmEntrypoint(build, deps, entrypointBaseUrl, onEntrypointLoaded) {
144146
if (!this._scriptLoaded) {
145147
this._scriptLoaded = true;
146148

147149
this._onEntrypointLoaded = onEntrypointLoaded;
148150
const { mainWasmPath, jsSupportRuntimePath } = build;
149-
const moduleUri = `${baseUri}${mainWasmPath}`;
150-
let jsSupportRuntimeUri = `${baseUri}${jsSupportRuntimePath}`;
151+
const moduleUri = joinPathSegments(baseUri, entrypointBaseUrl, mainWasmPath);
152+
let jsSupportRuntimeUri = joinPathSegments(baseUri, entrypointBaseUrl, jsSupportRuntimePath);
151153
if (this._ttPolicy != null) {
152154
jsSupportRuntimeUri = this._ttPolicy.createScriptURL(jsSupportRuntimeUri);
153155
}

lib/web_ui/flutter_js/src/loader.js

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { FlutterServiceWorkerLoader } from './service_worker_loader.js';
88
import { FlutterTrustedTypesPolicy } from './trusted_types.js';
99
import { loadCanvasKit } from './canvaskit_loader.js';
1010
import { loadSkwasm } from './skwasm_loader.js';
11+
import { getCanvaskitBaseUrl } from './utils.js';
1112

1213
/**
1314
* The public interface of _flutter.loader. Exposes two methods:
@@ -87,11 +88,25 @@ export class FlutterLoader {
8788
}
8889
}
8990

91+
/**
92+
* @param {import("./types").ApplicationBuild} build
93+
* @param {import("./types").WebRenderer} renderer
94+
**/
95+
const buildContainsRenderer = (build, renderer) => {
96+
switch (build.renderer) {
97+
// The "auto" build contains both canvaskit and html renderers.
98+
case "auto":
99+
return renderer == "canvaskit" || renderer == "html";
100+
default:
101+
return build.renderer == renderer;
102+
}
103+
}
104+
90105
const buildIsCompatible = (build) => {
91106
if (build.compileTarget === "dart2wasm" && !browserEnvironment.supportsWasmGC) {
92107
return false;
93108
}
94-
if (config.renderer && config.renderer != build.renderer) {
109+
if (config.renderer && !buildContainsRenderer(build, config.renderer)) {
95110
return false;
96111
}
97112
return rendererIsCompatible(build.renderer);
@@ -112,10 +127,11 @@ export class FlutterLoader {
112127
});
113128
}
114129

130+
const canvasKitBaseUrl = getCanvaskitBaseUrl(config, buildConfig);
115131
if (build.renderer === "canvaskit") {
116-
deps.canvasKit = loadCanvasKit(deps, config, browserEnvironment, buildConfig.engineRevision);
132+
deps.canvasKit = loadCanvasKit(deps, config, browserEnvironment, canvasKitBaseUrl);
117133
} else if (build.renderer === "skwasm") {
118-
deps.skwasm = loadSkwasm(deps, config, browserEnvironment, buildConfig.engineRevision);
134+
deps.skwasm = loadSkwasm(deps, config, browserEnvironment, canvasKitBaseUrl);
119135
}
120136

121137
// The FlutterEntrypointLoader instance could be injected as a dependency

lib/web_ui/flutter_js/src/service_worker_loader.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
import { baseUri } from "./base_uri.js";
5+
import { baseUri, joinPathSegments } from "./utils.js";
66

77
/**
88
* Wraps `promise` in a timeout of the given `duration` in ms.
@@ -78,7 +78,7 @@ export class FlutterServiceWorkerLoader {
7878
}
7979
const {
8080
serviceWorkerVersion,
81-
serviceWorkerUrl = `${baseUri}flutter_service_worker.js?v=${serviceWorkerVersion}`,
81+
serviceWorkerUrl = joinPathSegments(baseUri, `flutter_service_worker.js?v=${serviceWorkerVersion}`),
8282
timeoutMillis = 4000,
8383
} = settings;
8484
// Apply the TrustedTypes policy, if present.

lib/web_ui/flutter_js/src/skwasm_loader.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,21 @@
33
// found in the LICENSE file.
44

55
import { createWasmInstantiator } from "./instantiate_wasm.js";
6+
import { joinPathSegments } from "./utils.js";
67

7-
export const loadSkwasm = (deps, config, browserEnvironment, engineRevision) => {
8+
export const loadSkwasm = (deps, config, browserEnvironment, baseUrl) => {
89
return new Promise((resolve, reject) => {
9-
const baseUrl = config.canvasKitBaseUrl ?? `https://www.gstatic.com/flutter-canvaskit/${engineRevision}/`;
10-
let skwasmUrl = `${baseUrl}skwasm.js`;
10+
let skwasmUrl = joinPathSegments(baseUrl, "skwasm.js");
1111
if (deps.flutterTT.policy) {
1212
skwasmUrl = deps.flutterTT.policy.createScriptURL(skwasmUrl);
1313
}
14-
const wasmInstantiator = createWasmInstantiator(`${baseUrl}skwasm.wasm`);
14+
const wasmInstantiator = createWasmInstantiator(joinPathSegments(baseUrl, "skwasm.wasm"));
1515
const script = document.createElement("script");
1616
script.src = skwasmUrl;
1717
if (config.nonce) {
1818
script.nonce = config.nonce;
1919
}
20-
script.addEventListener('load', async () => {
20+
script.addEventListener("load", async () => {
2121
try {
2222
const skwasmInstance = await skwasm({
2323
instantiateWasm: wasmInstantiator,
@@ -28,10 +28,10 @@ export const loadSkwasm = (deps, config, browserEnvironment, engineRevision) =>
2828
// make sure that the worker JS can be loaded regardless of where
2929
// it is hosted.
3030
const url = scriptDirectory + fileName;
31-
if (url.endsWith('.worker.js')) {
31+
if (url.endsWith(".worker.js")) {
3232
return URL.createObjectURL(new Blob(
33-
[`importScripts('${url}');`],
34-
{ 'type': 'application/javascript' }));
33+
[`importScripts("${url}");`],
34+
{ "type": "application/javascript" }));
3535
}
3636
return url;
3737
}
@@ -41,7 +41,7 @@ export const loadSkwasm = (deps, config, browserEnvironment, engineRevision) =>
4141
reject(e);
4242
}
4343
});
44-
script.addEventListener('error', reject);
44+
script.addEventListener("error", reject);
4545
document.head.appendChild(script);
4646
});
4747
}

lib/web_ui/flutter_js/src/types.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ type WasmCompileTarget = "dart2wasm";
88
export type CompileTarget = JSCompileTarget | WasmCompileTarget;
99

1010
export type WebRenderer =
11+
"auto" |
1112
"html" |
1213
"canvaskit" |
1314
"skwasm";
@@ -32,6 +33,7 @@ export type ApplicationBuild = JSApplicationBuild | WasmApplicationBuild;
3233
export interface BuildConfig {
3334
serviceWorkerVersion: string;
3435
engineRevision: string;
36+
useLocalCanvasKit: bool?;
3537
builds: ApplicationBuild[];
3638
}
3739

@@ -54,6 +56,7 @@ export interface FlutterConfiguration {
5456
renderer: WebRenderer?;
5557
hostElement: HtmlElement?;
5658
fontFallbackBaseUrl: string?;
59+
entryPointBaseUrl: string?;
5760
}
5861

5962
export interface ServiceWorkerSettings {

lib/web_ui/flutter_js/src/utils.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
export const baseUri = getBaseURI();
6+
7+
function getBaseURI() {
8+
const base = document.querySelector("base");
9+
return (base && base.getAttribute("href")) || "";
10+
}
11+
12+
export function joinPathSegments(...segments) {
13+
return segments.filter((segment) => !!segment).map((segment, i) => {
14+
if (i === 0) {
15+
return stripRightSlashes(segment);
16+
} else {
17+
return stripLeftSlashes(stripRightSlashes(segment));
18+
}
19+
}).filter(x => x.length).join("/")
20+
}
21+
22+
function stripLeftSlashes(s) {
23+
let i = 0;
24+
while (i < s.length) {
25+
if (s.charCodeAt(i) !== "/") {
26+
break;
27+
}
28+
i++;
29+
}
30+
return s.substring(i);
31+
}
32+
33+
function stripRightSlashes(s) {
34+
let i = s.length;
35+
while (i > 0) {
36+
if (s.charCodeAt(i - 1) !== "/") {
37+
break;
38+
}
39+
i--;
40+
}
41+
return s.substring(0, i);
42+
}
43+
44+
/**
45+
* Calculates the proper base URL for CanvasKit/Skwasm assets.
46+
*
47+
* @param {import("./types").FlutterConfiguration} config
48+
* @param {import("./types").BuildConfig} buildConfig
49+
*/
50+
export function getCanvaskitBaseUrl(config, buildConfig) {
51+
if (config.canvasKitBaseUrl) {
52+
return config.canvasKitBaseUrl;
53+
}
54+
if (buildConfig.engineRevision && !buildConfig.useLocalCanvasKit) {
55+
return joinPathSegments("https://www.gstatic.com/flutter-canvaskit", buildConfig.engineRevision);
56+
}
57+
return "/canvaskit";
58+
}

0 commit comments

Comments
 (0)