Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion lib/web_ui/dev/test_platform.dart
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,7 @@ class BrowserPlatform extends PlatformPlugin {
</script>
<script>
_flutter.buildConfig = {
useLocalCanvaskit: true,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty!

builds: [
$buildConfigsString
]
Expand All @@ -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()}",
Expand Down
2 changes: 1 addition & 1 deletion lib/web_ui/flutter_js/sources.gni
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
]
17 changes: 0 additions & 17 deletions lib/web_ui/flutter_js/src/base_uri.js

This file was deleted.

15 changes: 8 additions & 7 deletions lib/web_ui/flutter_js/src/canvaskit_loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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,
Expand All @@ -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;
Expand Down
16 changes: 9 additions & 7 deletions lib/web_ui/flutter_js/src/entrypoint_loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}
}
Expand Down Expand Up @@ -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);
}
Expand Down
22 changes: 19 additions & 3 deletions lib/web_ui/flutter_js/src/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions lib/web_ui/flutter_js/src/service_worker_loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
18 changes: 9 additions & 9 deletions lib/web_ui/flutter_js/src/skwasm_loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;
}
Expand All @@ -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);
});
}
3 changes: 3 additions & 0 deletions lib/web_ui/flutter_js/src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type WasmCompileTarget = "dart2wasm";
export type CompileTarget = JSCompileTarget | WasmCompileTarget;

export type WebRenderer =
"auto" |
"html" |
"canvaskit" |
"skwasm";
Expand All @@ -32,6 +33,7 @@ export type ApplicationBuild = JSApplicationBuild | WasmApplicationBuild;
export interface BuildConfig {
serviceWorkerVersion: string;
engineRevision: string;
useLocalCanvasKit: bool?;
builds: ApplicationBuild[];
}

Expand All @@ -54,6 +56,7 @@ export interface FlutterConfiguration {
renderer: WebRenderer?;
hostElement: HtmlElement?;
fontFallbackBaseUrl: string?;
entryPointBaseUrl: string?;
}

export interface ServiceWorkerSettings {
Expand Down
58 changes: 58 additions & 0 deletions lib/web_ui/flutter_js/src/utils.js
Original file line number Diff line number Diff line change
@@ -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";
}