Fixes a few issues in flutter_js (flutter/engine#53231)
This addresses a couple things: https://github.com/flutter/flutter/issues/147610 (Treat `auto` renderer properly) https://github.com/flutter/flutter/issues/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 https://github.com/flutter/flutter/issues/148713
This commit is contained in:
@@ -42761,7 +42761,6 @@ ORIGIN: ../../../flutter/lib/ui/window/pointer_data_packet_converter.cc + ../../
|
||||
ORIGIN: ../../../flutter/lib/ui/window/pointer_data_packet_converter.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/ui/window/viewport_metrics.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/ui/window/viewport_metrics.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/web_ui/flutter_js/src/base_uri.js + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/web_ui/flutter_js/src/browser_environment.js + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/web_ui/flutter_js/src/canvaskit_loader.js + ../../../flutter/LICENSE
|
||||
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/
|
||||
ORIGIN: ../../../flutter/lib/web_ui/flutter_js/src/service_worker_loader.js + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/web_ui/flutter_js/src/skwasm_loader.js + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/web_ui/flutter_js/src/trusted_types.js + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/web_ui/flutter_js/src/utils.js + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/web_ui/lib/annotations.dart + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/web_ui/lib/canvas.dart + ../../../flutter/LICENSE
|
||||
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
|
||||
FILE: ../../../flutter/lib/ui/window/pointer_data_packet_converter.h
|
||||
FILE: ../../../flutter/lib/ui/window/viewport_metrics.cc
|
||||
FILE: ../../../flutter/lib/ui/window/viewport_metrics.h
|
||||
FILE: ../../../flutter/lib/web_ui/flutter_js/src/base_uri.js
|
||||
FILE: ../../../flutter/lib/web_ui/flutter_js/src/browser_environment.js
|
||||
FILE: ../../../flutter/lib/web_ui/flutter_js/src/canvaskit_loader.js
|
||||
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
|
||||
FILE: ../../../flutter/lib/web_ui/flutter_js/src/skwasm_loader.js
|
||||
FILE: ../../../flutter/lib/web_ui/flutter_js/src/trusted_types.js
|
||||
FILE: ../../../flutter/lib/web_ui/flutter_js/src/types.d.ts
|
||||
FILE: ../../../flutter/lib/web_ui/flutter_js/src/utils.js
|
||||
FILE: ../../../flutter/lib/web_ui/lib/annotations.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/canvas.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/channel_buffers.dart
|
||||
|
||||
@@ -562,6 +562,7 @@ class BrowserPlatform extends PlatformPlugin {
|
||||
</script>
|
||||
<script>
|
||||
_flutter.buildConfig = {
|
||||
useLocalCanvaskit: true,
|
||||
builds: [
|
||||
$buildConfigsString
|
||||
]
|
||||
@@ -571,7 +572,6 @@ class BrowserPlatform extends PlatformPlugin {
|
||||
<script>
|
||||
_flutter.loader.load({
|
||||
config: {
|
||||
canvasKitBaseUrl: "/canvaskit/",
|
||||
// Some of our tests rely on color emoji
|
||||
useColorEmoji: true,
|
||||
canvasKitVariant: "${getCanvasKitVariant()}",
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
# found in the LICENSE file.
|
||||
|
||||
flutter_js_source_list = [
|
||||
"src/base_uri.js",
|
||||
"src/browser_environment.js",
|
||||
"src/canvaskit_loader.js",
|
||||
"src/entrypoint_loader.js",
|
||||
@@ -13,6 +12,7 @@ flutter_js_source_list = [
|
||||
"src/service_worker_loader.js",
|
||||
"src/skwasm_loader.js",
|
||||
"src/trusted_types.js",
|
||||
"src/utils.js",
|
||||
|
||||
"src/types.d.ts",
|
||||
]
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
export const baseUri = ensureTrailingSlash(getBaseURI());
|
||||
|
||||
function getBaseURI() {
|
||||
const base = document.querySelector("base");
|
||||
return (base && base.getAttribute("href")) || "";
|
||||
}
|
||||
|
||||
function ensureTrailingSlash(uri) {
|
||||
if (uri === "") {
|
||||
return uri;
|
||||
}
|
||||
return uri.endsWith("/") ? uri : `${uri}/`;
|
||||
}
|
||||
@@ -3,8 +3,9 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import { createWasmInstantiator } from "./instantiate_wasm.js";
|
||||
import { joinPathSegments } from "./utils.js";
|
||||
|
||||
export const loadCanvasKit = (deps, config, browserEnvironment, engineRevision) => {
|
||||
export const loadCanvasKit = (deps, config, browserEnvironment, canvasKitBaseUrl) => {
|
||||
if (window.flutterCanvasKit) {
|
||||
// The user has set this global variable ahead of time, so we just return that.
|
||||
return Promise.resolve(window.flutterCanvasKit);
|
||||
@@ -15,21 +16,21 @@ export const loadCanvasKit = (deps, config, browserEnvironment, engineRevision)
|
||||
throw "Chromium CanvasKit variant specifically requested, but unsupported in this browser";
|
||||
}
|
||||
const useChromiumCanvasKit = supportsChromiumCanvasKit && (config.canvasKitVariant !== "full");
|
||||
let baseUrl = config.canvasKitBaseUrl ?? `https://www.gstatic.com/flutter-canvaskit/${engineRevision}/`;
|
||||
let baseUrl = canvasKitBaseUrl;
|
||||
if (useChromiumCanvasKit) {
|
||||
baseUrl = `${baseUrl}chromium/`;
|
||||
baseUrl = joinPathSegments(baseUrl, "chromium");
|
||||
}
|
||||
let canvasKitUrl = `${baseUrl}canvaskit.js`;
|
||||
let canvasKitUrl = joinPathSegments(baseUrl, "canvaskit.js");
|
||||
if (deps.flutterTT.policy) {
|
||||
canvasKitUrl = deps.flutterTT.policy.createScriptURL(canvasKitUrl);
|
||||
}
|
||||
const wasmInstantiator = createWasmInstantiator(`${baseUrl}canvaskit.wasm`);
|
||||
const wasmInstantiator = createWasmInstantiator(joinPathSegments(baseUrl, "canvaskit.wasm"));
|
||||
const script = document.createElement("script");
|
||||
script.src = canvasKitUrl;
|
||||
if (config.nonce) {
|
||||
script.nonce = config.nonce;
|
||||
}
|
||||
script.addEventListener('load', async () => {
|
||||
script.addEventListener("load", async () => {
|
||||
try {
|
||||
const canvasKit = await CanvasKitInit({
|
||||
instantiateWasm: wasmInstantiator,
|
||||
@@ -40,7 +41,7 @@ export const loadCanvasKit = (deps, config, browserEnvironment, engineRevision)
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
script.addEventListener('error', reject);
|
||||
script.addEventListener("error", reject);
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
return window.flutterCanvasKitLoaded;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import { baseUri } from "./base_uri.js";
|
||||
import { baseUri, joinPathSegments } from "./utils.js";
|
||||
|
||||
/**
|
||||
* Handles injecting the main Flutter web entrypoint (main.dart.js), and notifying
|
||||
@@ -37,7 +37,7 @@ export class FlutterEntrypointLoader {
|
||||
* Returns undefined when an `onEntrypointLoaded` callback is supplied in `options`.
|
||||
*/
|
||||
async loadEntrypoint(options) {
|
||||
const { entrypointUrl = `${baseUri}main.dart.js`, onEntrypointLoaded, nonce } =
|
||||
const { entrypointUrl = joinPathSegments(baseUri, "main.dart.js"), onEntrypointLoaded, nonce } =
|
||||
options || {};
|
||||
return this._loadJSEntrypoint(entrypointUrl, onEntrypointLoaded, nonce);
|
||||
}
|
||||
@@ -63,11 +63,12 @@ export class FlutterEntrypointLoader {
|
||||
onEntrypointLoaded ??= (engineInitializer) => {
|
||||
engineInitializer.initializeEngine(config).then((appRunner) => appRunner.runApp())
|
||||
};
|
||||
const { entryPointBaseUrl } = config;
|
||||
if (build.compileTarget === "dart2wasm") {
|
||||
return this._loadWasmEntrypoint(build, deps, onEntrypointLoaded);
|
||||
return this._loadWasmEntrypoint(build, deps, entryPointBaseUrl, onEntrypointLoaded);
|
||||
} else {
|
||||
const mainPath = build.mainJsPath ?? "main.dart.js";
|
||||
const entrypointUrl = `${baseUri}${mainPath}`;
|
||||
const entrypointUrl = joinPathSegments(baseUri, entryPointBaseUrl, mainPath);
|
||||
return this._loadJSEntrypoint(entrypointUrl, onEntrypointLoaded, nonce);
|
||||
}
|
||||
}
|
||||
@@ -138,16 +139,17 @@ export class FlutterEntrypointLoader {
|
||||
*
|
||||
* @param {import("./types").WasmApplicationBuild} build
|
||||
* @param {*} deps
|
||||
* @param {string} entryPointBaseUrl
|
||||
* @param {import("./types").OnEntrypointLoadedCallback} onEntrypointLoaded
|
||||
*/
|
||||
async _loadWasmEntrypoint(build, deps, onEntrypointLoaded) {
|
||||
async _loadWasmEntrypoint(build, deps, entrypointBaseUrl, onEntrypointLoaded) {
|
||||
if (!this._scriptLoaded) {
|
||||
this._scriptLoaded = true;
|
||||
|
||||
this._onEntrypointLoaded = onEntrypointLoaded;
|
||||
const { mainWasmPath, jsSupportRuntimePath } = build;
|
||||
const moduleUri = `${baseUri}${mainWasmPath}`;
|
||||
let jsSupportRuntimeUri = `${baseUri}${jsSupportRuntimePath}`;
|
||||
const moduleUri = joinPathSegments(baseUri, entrypointBaseUrl, mainWasmPath);
|
||||
let jsSupportRuntimeUri = joinPathSegments(baseUri, entrypointBaseUrl, jsSupportRuntimePath);
|
||||
if (this._ttPolicy != null) {
|
||||
jsSupportRuntimeUri = this._ttPolicy.createScriptURL(jsSupportRuntimeUri);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { FlutterServiceWorkerLoader } from './service_worker_loader.js';
|
||||
import { FlutterTrustedTypesPolicy } from './trusted_types.js';
|
||||
import { loadCanvasKit } from './canvaskit_loader.js';
|
||||
import { loadSkwasm } from './skwasm_loader.js';
|
||||
import { getCanvaskitBaseUrl } from './utils.js';
|
||||
|
||||
/**
|
||||
* The public interface of _flutter.loader. Exposes two methods:
|
||||
@@ -87,11 +88,25 @@ export class FlutterLoader {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("./types").ApplicationBuild} build
|
||||
* @param {import("./types").WebRenderer} renderer
|
||||
**/
|
||||
const buildContainsRenderer = (build, renderer) => {
|
||||
switch (build.renderer) {
|
||||
// The "auto" build contains both canvaskit and html renderers.
|
||||
case "auto":
|
||||
return renderer == "canvaskit" || renderer == "html";
|
||||
default:
|
||||
return build.renderer == renderer;
|
||||
}
|
||||
}
|
||||
|
||||
const buildIsCompatible = (build) => {
|
||||
if (build.compileTarget === "dart2wasm" && !browserEnvironment.supportsWasmGC) {
|
||||
return false;
|
||||
}
|
||||
if (config.renderer && config.renderer != build.renderer) {
|
||||
if (config.renderer && !buildContainsRenderer(build, config.renderer)) {
|
||||
return false;
|
||||
}
|
||||
return rendererIsCompatible(build.renderer);
|
||||
@@ -112,10 +127,11 @@ export class FlutterLoader {
|
||||
});
|
||||
}
|
||||
|
||||
const canvasKitBaseUrl = getCanvaskitBaseUrl(config, buildConfig);
|
||||
if (build.renderer === "canvaskit") {
|
||||
deps.canvasKit = loadCanvasKit(deps, config, browserEnvironment, buildConfig.engineRevision);
|
||||
deps.canvasKit = loadCanvasKit(deps, config, browserEnvironment, canvasKitBaseUrl);
|
||||
} else if (build.renderer === "skwasm") {
|
||||
deps.skwasm = loadSkwasm(deps, config, browserEnvironment, buildConfig.engineRevision);
|
||||
deps.skwasm = loadSkwasm(deps, config, browserEnvironment, canvasKitBaseUrl);
|
||||
}
|
||||
|
||||
// The FlutterEntrypointLoader instance could be injected as a dependency
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import { baseUri } from "./base_uri.js";
|
||||
import { baseUri, joinPathSegments } from "./utils.js";
|
||||
|
||||
/**
|
||||
* Wraps `promise` in a timeout of the given `duration` in ms.
|
||||
@@ -78,7 +78,7 @@ export class FlutterServiceWorkerLoader {
|
||||
}
|
||||
const {
|
||||
serviceWorkerVersion,
|
||||
serviceWorkerUrl = `${baseUri}flutter_service_worker.js?v=${serviceWorkerVersion}`,
|
||||
serviceWorkerUrl = joinPathSegments(baseUri, `flutter_service_worker.js?v=${serviceWorkerVersion}`),
|
||||
timeoutMillis = 4000,
|
||||
} = settings;
|
||||
// Apply the TrustedTypes policy, if present.
|
||||
|
||||
@@ -3,21 +3,21 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import { createWasmInstantiator } from "./instantiate_wasm.js";
|
||||
import { joinPathSegments } from "./utils.js";
|
||||
|
||||
export const loadSkwasm = (deps, config, browserEnvironment, engineRevision) => {
|
||||
export const loadSkwasm = (deps, config, browserEnvironment, baseUrl) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const baseUrl = config.canvasKitBaseUrl ?? `https://www.gstatic.com/flutter-canvaskit/${engineRevision}/`;
|
||||
let skwasmUrl = `${baseUrl}skwasm.js`;
|
||||
let skwasmUrl = joinPathSegments(baseUrl, "skwasm.js");
|
||||
if (deps.flutterTT.policy) {
|
||||
skwasmUrl = deps.flutterTT.policy.createScriptURL(skwasmUrl);
|
||||
}
|
||||
const wasmInstantiator = createWasmInstantiator(`${baseUrl}skwasm.wasm`);
|
||||
const wasmInstantiator = createWasmInstantiator(joinPathSegments(baseUrl, "skwasm.wasm"));
|
||||
const script = document.createElement("script");
|
||||
script.src = skwasmUrl;
|
||||
if (config.nonce) {
|
||||
script.nonce = config.nonce;
|
||||
}
|
||||
script.addEventListener('load', async () => {
|
||||
script.addEventListener("load", async () => {
|
||||
try {
|
||||
const skwasmInstance = await skwasm({
|
||||
instantiateWasm: wasmInstantiator,
|
||||
@@ -28,10 +28,10 @@ export const loadSkwasm = (deps, config, browserEnvironment, engineRevision) =>
|
||||
// make sure that the worker JS can be loaded regardless of where
|
||||
// it is hosted.
|
||||
const url = scriptDirectory + fileName;
|
||||
if (url.endsWith('.worker.js')) {
|
||||
if (url.endsWith(".worker.js")) {
|
||||
return URL.createObjectURL(new Blob(
|
||||
[`importScripts('${url}');`],
|
||||
{ 'type': 'application/javascript' }));
|
||||
[`importScripts("${url}");`],
|
||||
{ "type": "application/javascript" }));
|
||||
}
|
||||
return url;
|
||||
}
|
||||
@@ -41,7 +41,7 @@ export const loadSkwasm = (deps, config, browserEnvironment, engineRevision) =>
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
script.addEventListener('error', reject);
|
||||
script.addEventListener("error", reject);
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ type WasmCompileTarget = "dart2wasm";
|
||||
export type CompileTarget = JSCompileTarget | WasmCompileTarget;
|
||||
|
||||
export type WebRenderer =
|
||||
"auto" |
|
||||
"html" |
|
||||
"canvaskit" |
|
||||
"skwasm";
|
||||
@@ -32,6 +33,7 @@ export type ApplicationBuild = JSApplicationBuild | WasmApplicationBuild;
|
||||
export interface BuildConfig {
|
||||
serviceWorkerVersion: string;
|
||||
engineRevision: string;
|
||||
useLocalCanvasKit: bool?;
|
||||
builds: ApplicationBuild[];
|
||||
}
|
||||
|
||||
@@ -54,6 +56,7 @@ export interface FlutterConfiguration {
|
||||
renderer: WebRenderer?;
|
||||
hostElement: HtmlElement?;
|
||||
fontFallbackBaseUrl: string?;
|
||||
entryPointBaseUrl: string?;
|
||||
}
|
||||
|
||||
export interface ServiceWorkerSettings {
|
||||
|
||||
58
engine/src/flutter/lib/web_ui/flutter_js/src/utils.js
Normal file
58
engine/src/flutter/lib/web_ui/flutter_js/src/utils.js
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
export const baseUri = getBaseURI();
|
||||
|
||||
function getBaseURI() {
|
||||
const base = document.querySelector("base");
|
||||
return (base && base.getAttribute("href")) || "";
|
||||
}
|
||||
|
||||
export function joinPathSegments(...segments) {
|
||||
return segments.filter((segment) => !!segment).map((segment, i) => {
|
||||
if (i === 0) {
|
||||
return stripRightSlashes(segment);
|
||||
} else {
|
||||
return stripLeftSlashes(stripRightSlashes(segment));
|
||||
}
|
||||
}).filter(x => x.length).join("/")
|
||||
}
|
||||
|
||||
function stripLeftSlashes(s) {
|
||||
let i = 0;
|
||||
while (i < s.length) {
|
||||
if (s.charCodeAt(i) !== "/") {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return s.substring(i);
|
||||
}
|
||||
|
||||
function stripRightSlashes(s) {
|
||||
let i = s.length;
|
||||
while (i > 0) {
|
||||
if (s.charCodeAt(i - 1) !== "/") {
|
||||
break;
|
||||
}
|
||||
i--;
|
||||
}
|
||||
return s.substring(0, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the proper base URL for CanvasKit/Skwasm assets.
|
||||
*
|
||||
* @param {import("./types").FlutterConfiguration} config
|
||||
* @param {import("./types").BuildConfig} buildConfig
|
||||
*/
|
||||
export function getCanvaskitBaseUrl(config, buildConfig) {
|
||||
if (config.canvasKitBaseUrl) {
|
||||
return config.canvasKitBaseUrl;
|
||||
}
|
||||
if (buildConfig.engineRevision && !buildConfig.useLocalCanvasKit) {
|
||||
return joinPathSegments("https://www.gstatic.com/flutter-canvaskit", buildConfig.engineRevision);
|
||||
}
|
||||
return "/canvaskit";
|
||||
}
|
||||
Reference in New Issue
Block a user