Have flutter.js load local canvaskit instead of the CDN when appropriate (#150806)

If the user specifies the `--no-web-resources-cdn` or `--local-web-sdk`, we should use the local version of CanvasKit. `flutter.js` now has a flag that can be specified in the build configuration that tells it to load locally instead.

Also, added a link to the relevant docs in the web template warnings.

This addresses https://github.com/flutter/flutter/issues/148713
Also fixes https://github.com/flutter/flutter/issues/145559
This commit is contained in:
Jackson Gardner 2024-06-27 11:44:04 -07:00 committed by GitHub
parent ab4d422213
commit 74688cea3d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 213 additions and 62 deletions

View File

@ -46,6 +46,7 @@ class BuildInfo {
this.initializeFromDill, this.initializeFromDill,
this.assumeInitializeFromDillUpToDate = false, this.assumeInitializeFromDillUpToDate = false,
this.buildNativeAssets = true, this.buildNativeAssets = true,
this.useLocalCanvasKit = false,
}) : extraFrontEndOptions = extraFrontEndOptions ?? const <String>[], }) : extraFrontEndOptions = extraFrontEndOptions ?? const <String>[],
extraGenSnapshotOptions = extraGenSnapshotOptions ?? const <String>[], extraGenSnapshotOptions = extraGenSnapshotOptions ?? const <String>[],
fileSystemRoots = fileSystemRoots ?? const <String>[], fileSystemRoots = fileSystemRoots ?? const <String>[],
@ -180,6 +181,9 @@ class BuildInfo {
/// If set, builds native assets with `build.dart` from all packages. /// If set, builds native assets with `build.dart` from all packages.
final bool buildNativeAssets; final bool buildNativeAssets;
/// If set, web builds will use the locally built CanvasKit instead of using the CDN
final bool useLocalCanvasKit;
static const BuildInfo debug = BuildInfo(BuildMode.debug, null, trackWidgetCreation: true, treeShakeIcons: false); static const BuildInfo debug = BuildInfo(BuildMode.debug, null, trackWidgetCreation: true, treeShakeIcons: false);
static const BuildInfo profile = BuildInfo(BuildMode.profile, null, treeShakeIcons: kIconTreeShakerEnabledDefault); static const BuildInfo profile = BuildInfo(BuildMode.profile, null, treeShakeIcons: kIconTreeShakerEnabledDefault);
static const BuildInfo jitRelease = BuildInfo(BuildMode.jitRelease, null, treeShakeIcons: kIconTreeShakerEnabledDefault); static const BuildInfo jitRelease = BuildInfo(BuildMode.jitRelease, null, treeShakeIcons: kIconTreeShakerEnabledDefault);
@ -260,6 +264,8 @@ class BuildInfo {
kBuildName: buildName!, kBuildName: buildName!,
if (buildNumber != null) if (buildNumber != null)
kBuildNumber: buildNumber!, kBuildNumber: buildNumber!,
if (useLocalCanvasKit)
kUseLocalCanvasKitFlag: useLocalCanvasKit.toString(),
}; };
} }
@ -941,6 +947,9 @@ const String kCodesignIdentity = 'CodesignIdentity';
/// only the glyphs used by the application. /// only the glyphs used by the application.
const String kIconTreeShakerFlag = 'TreeShakeIcons'; const String kIconTreeShakerFlag = 'TreeShakeIcons';
/// Controls whether a web build should use local canvaskit or the CDN
const String kUseLocalCanvasKitFlag = 'UseLocalCanvasKit';
/// The input key for an SkSL bundle path. /// The input key for an SkSL bundle path.
const String kBundleSkSLPath = 'BundleSkSLPath'; const String kBundleSkSLPath = 'BundleSkSLPath';

View File

@ -104,6 +104,19 @@ abstract class Dart2WebTarget extends Target {
Iterable<File> buildFiles(Environment environment); Iterable<File> buildFiles(Environment environment);
Iterable<String> get buildPatternStems; Iterable<String> get buildPatternStems;
List<String> computeDartDefines(Environment environment) {
final List<String> dartDefines = compilerConfig.renderer.updateDartDefines(
decodeDartDefines(environment.defines, kDartDefines),
);
if (environment.defines[kUseLocalCanvasKitFlag] != 'true') {
final bool canvasKitUrlAlreadySet = dartDefines.any((String define) => define.startsWith('FLUTTER_WEB_CANVASKIT_URL='));
if (!canvasKitUrlAlreadySet) {
dartDefines.add('FLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/${globals.flutterVersion.engineRevision}/');
}
}
return dartDefines;
}
@override @override
List<Target> get dependencies => const <Target>[ List<Target> get dependencies => const <Target>[
WebEntrypointTarget(), WebEntrypointTarget(),
@ -155,9 +168,6 @@ class Dart2JSTarget extends Dart2WebTarget {
final BuildMode buildMode = BuildMode.fromCliName(buildModeEnvironment); final BuildMode buildMode = BuildMode.fromCliName(buildModeEnvironment);
final Artifacts artifacts = environment.artifacts; final Artifacts artifacts = environment.artifacts;
final String platformBinariesPath = artifacts.getHostArtifact(HostArtifact.webPlatformKernelFolder).path; final String platformBinariesPath = artifacts.getHostArtifact(HostArtifact.webPlatformKernelFolder).path;
final List<String> dartDefines = compilerConfig.renderer.updateDartDefines(
decodeDartDefines(environment.defines, kDartDefines),
);
final List<String> sharedCommandOptions = <String>[ final List<String> sharedCommandOptions = <String>[
artifacts.getArtifactPath(Artifact.engineDartBinary, platform: TargetPlatform.web_javascript), artifacts.getArtifactPath(Artifact.engineDartBinary, platform: TargetPlatform.web_javascript),
'--disable-dart-dev', '--disable-dart-dev',
@ -169,7 +179,7 @@ class Dart2JSTarget extends Dart2WebTarget {
'-Ddart.vm.profile=true' '-Ddart.vm.profile=true'
else else
'-Ddart.vm.product=true', '-Ddart.vm.product=true',
for (final String dartDefine in dartDefines) for (final String dartDefine in computeDartDefines(environment))
'-D$dartDefine', '-D$dartDefine',
]; ];
@ -287,9 +297,6 @@ class Dart2WasmTarget extends Dart2WebTarget {
final File depFile = environment.buildDir.childFile('dart2wasm.d'); final File depFile = environment.buildDir.childFile('dart2wasm.d');
final String platformBinariesPath = artifacts.getHostArtifact(HostArtifact.webPlatformKernelFolder).path; final String platformBinariesPath = artifacts.getHostArtifact(HostArtifact.webPlatformKernelFolder).path;
final String platformFilePath = environment.fileSystem.path.join(platformBinariesPath, 'dart2wasm_platform.dill'); final String platformFilePath = environment.fileSystem.path.join(platformBinariesPath, 'dart2wasm_platform.dill');
final List<String> dartDefines = compilerConfig.renderer.updateDartDefines(
decodeDartDefines(environment.defines, kDartDefines),
);
assert(buildMode == BuildMode.release || buildMode == BuildMode.profile); assert(buildMode == BuildMode.release || buildMode == BuildMode.profile);
final List<String> compilationArgs = <String>[ final List<String> compilationArgs = <String>[
@ -309,7 +316,7 @@ class Dart2WasmTarget extends Dart2WebTarget {
else else
'-Ddart.vm.product=true', '-Ddart.vm.product=true',
...decodeCommaSeparated(environment.defines, kExtraFrontEndOptions), ...decodeCommaSeparated(environment.defines, kExtraFrontEndOptions),
for (final String dartDefine in dartDefines) for (final String dartDefine in computeDartDefines(environment))
'-D$dartDefine', '-D$dartDefine',
'--extra-compiler-option=--depfile=${depFile.path}', '--extra-compiler-option=--depfile=${depFile.path}',
@ -380,23 +387,9 @@ class WebReleaseBundle extends Target {
WebReleaseBundle._({ WebReleaseBundle._({
required this.compileTargets, required this.compileTargets,
}) : templatedFilesTarget = WebTemplatedFiles(generateBuildConfigString(compileTargets)); }) : templatedFilesTarget = WebTemplatedFiles(
compileTargets.map((Dart2WebTarget target) => target.buildConfig).toList()
static String generateBuildConfigString(List<Dart2WebTarget> compileTargets) { );
final List<Map<String, Object?>> buildDescriptions = compileTargets.map(
(Dart2WebTarget target) => target.buildConfig
).toList();
final Map<String, Object?> buildConfig = <String, Object?>{
'engineRevision': globals.flutterVersion.engineRevision,
'builds': buildDescriptions,
};
return '''
if (!window._flutter) {
window._flutter = {};
}
_flutter.buildConfig = ${jsonEncode(buildConfig)};
''';
}
final List<Dart2WebTarget> compileTargets; final List<Dart2WebTarget> compileTargets;
final WebTemplatedFiles templatedFilesTarget; final WebTemplatedFiles templatedFilesTarget;
@ -516,12 +509,12 @@ _flutter.buildConfig = ${jsonEncode(buildConfig)};
} }
class WebTemplatedFiles extends Target { class WebTemplatedFiles extends Target {
WebTemplatedFiles(this.buildConfigString); WebTemplatedFiles(this.buildDescriptions);
final String buildConfigString; final List<Map<String, Object?>> buildDescriptions;
@override @override
String get buildKey => buildConfigString; String get buildKey => jsonEncode(buildDescriptions);
void _emitWebTemplateWarning( void _emitWebTemplateWarning(
Environment environment, Environment environment,
@ -533,6 +526,21 @@ class WebTemplatedFiles extends Target {
); );
} }
String buildConfigString(Environment environment) {
final Map<String, Object> buildConfig = <String, Object>{
'engineRevision': globals.flutterVersion.engineRevision,
'builds': buildDescriptions,
if (environment.defines[kUseLocalCanvasKitFlag] == 'true')
'useLocalCanvasKit': true,
};
return '''
if (!window._flutter) {
window._flutter = {};
}
_flutter.buildConfig = ${jsonEncode(buildConfig)};
''';
}
@override @override
Future<void> build(Environment environment) async { Future<void> build(Environment environment) async {
final Directory webResources = environment.projectDir final Directory webResources = environment.projectDir
@ -555,6 +563,8 @@ class WebTemplatedFiles extends Target {
'flutter.js', 'flutter.js',
)); ));
final String buildConfig = buildConfigString(environment);
// Insert a random hash into the requests for service_worker.js. This is not a content hash, // Insert a random hash into the requests for service_worker.js. This is not a content hash,
// because it would need to be the hash for the entire bundle and not just the resource // because it would need to be the hash for the entire bundle and not just the resource
// in question. // in question.
@ -563,7 +573,7 @@ class WebTemplatedFiles extends Target {
baseHref: '', baseHref: '',
serviceWorkerVersion: serviceWorkerVersion, serviceWorkerVersion: serviceWorkerVersion,
flutterJsFile: flutterJsFile, flutterJsFile: flutterJsFile,
buildConfig: buildConfigString, buildConfig: buildConfig,
); );
final File outputFlutterBootstrapJs = fileSystem.file(fileSystem.path.join( final File outputFlutterBootstrapJs = fileSystem.file(fileSystem.path.join(
@ -585,7 +595,7 @@ class WebTemplatedFiles extends Target {
baseHref: environment.defines[kBaseHref] ?? '/', baseHref: environment.defines[kBaseHref] ?? '/',
serviceWorkerVersion: serviceWorkerVersion, serviceWorkerVersion: serviceWorkerVersion,
flutterJsFile: flutterJsFile, flutterJsFile: flutterJsFile,
buildConfig: buildConfigString, buildConfig: buildConfig,
flutterBootstrapJs: bootstrapTemplate.content, flutterBootstrapJs: bootstrapTemplate.content,
); );
final File outputIndexHtml = fileSystem.file(fileSystem.path.join( final File outputIndexHtml = fileSystem.file(fileSystem.path.join(

View File

@ -235,6 +235,19 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
bool get useWasm => boolArg(FlutterOptions.kWebWasmFlag); bool get useWasm => boolArg(FlutterOptions.kWebWasmFlag);
bool get useLocalCanvasKit {
// If we have specified not to use CDN, use local CanvasKit
if (!boolArg(FlutterOptions.kWebResourcesCdnFlag)) {
return true;
}
// If we are using a locally built web sdk, we should use local CanvasKit
if (stringArg(FlutterGlobalOptions.kLocalWebSDKOption, global: true) != null) {
return true;
}
return false;
}
WebRendererMode get webRenderer => WebRendererMode.fromCliOption( WebRendererMode get webRenderer => WebRendererMode.fromCliOption(
stringArg(FlutterOptions.kWebRendererFlag), stringArg(FlutterOptions.kWebRendererFlag),
useWasm: useWasm useWasm: useWasm
@ -274,6 +287,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
webHeaders: webHeaders, webHeaders: webHeaders,
webRenderer: webRenderer, webRenderer: webRenderer,
webUseWasm: useWasm, webUseWasm: useWasm,
webUseLocalCanvaskit: useLocalCanvasKit,
enableImpeller: enableImpeller, enableImpeller: enableImpeller,
enableVulkanValidation: enableVulkanValidation, enableVulkanValidation: enableVulkanValidation,
uninstallFirst: uninstallFirst, uninstallFirst: uninstallFirst,
@ -325,6 +339,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
webHeaders: webHeaders, webHeaders: webHeaders,
webRenderer: webRenderer, webRenderer: webRenderer,
webUseWasm: useWasm, webUseWasm: useWasm,
webUseLocalCanvaskit: useLocalCanvasKit,
vmserviceOutFile: stringArg('vmservice-out-file'), vmserviceOutFile: stringArg('vmservice-out-file'),
fastStart: argParser.options.containsKey('fast-start') fastStart: argParser.options.containsKey('fast-start')
&& boolArg('fast-start') && boolArg('fast-start')

View File

@ -412,6 +412,7 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
debugLogsDirectoryPath: debugLogsDirectoryPath, debugLogsDirectoryPath: debugLogsDirectoryPath,
webRenderer: webRenderer, webRenderer: webRenderer,
webUseWasm: useWasm, webUseWasm: useWasm,
webUseLocalCanvaskit: true,
); );
String? testAssetDirectory; String? testAssetDirectory;

View File

@ -994,6 +994,7 @@ class DebuggingOptions {
this.webLaunchUrl, this.webLaunchUrl,
WebRendererMode? webRenderer, WebRendererMode? webRenderer,
this.webUseWasm = false, this.webUseWasm = false,
this.webUseLocalCanvaskit = false,
this.vmserviceOutFile, this.vmserviceOutFile,
this.fastStart = false, this.fastStart = false,
this.nullAssertions = false, this.nullAssertions = false,
@ -1026,6 +1027,7 @@ class DebuggingOptions {
this.webHeaders = const <String, String>{}, this.webHeaders = const <String, String>{},
WebRendererMode? webRenderer, WebRendererMode? webRenderer,
this.webUseWasm = false, this.webUseWasm = false,
this.webUseLocalCanvaskit = false,
this.cacheSkSL = false, this.cacheSkSL = false,
this.traceAllowlist, this.traceAllowlist,
this.enableImpeller = ImpellerStatus.platformDefault, this.enableImpeller = ImpellerStatus.platformDefault,
@ -1108,6 +1110,7 @@ class DebuggingOptions {
required this.webLaunchUrl, required this.webLaunchUrl,
required this.webRenderer, required this.webRenderer,
required this.webUseWasm, required this.webUseWasm,
required this.webUseLocalCanvaskit,
required this.vmserviceOutFile, required this.vmserviceOutFile,
required this.fastStart, required this.fastStart,
required this.nullAssertions, required this.nullAssertions,
@ -1198,6 +1201,9 @@ class DebuggingOptions {
/// Whether to compile to webassembly /// Whether to compile to webassembly
final bool webUseWasm; final bool webUseWasm;
/// If true, serve CanvasKit assets locally rather than using the CDN.
final bool webUseLocalCanvaskit;
/// A file where the VM Service URL should be written after the application is started. /// A file where the VM Service URL should be written after the application is started.
final String? vmserviceOutFile; final String? vmserviceOutFile;
final bool fastStart; final bool fastStart;
@ -1308,6 +1314,7 @@ class DebuggingOptions {
'webHeaders': webHeaders, 'webHeaders': webHeaders,
'webRenderer': webRenderer.name, 'webRenderer': webRenderer.name,
'webUseWasm': webUseWasm, 'webUseWasm': webUseWasm,
'webUseLocalCanvaskit': webUseLocalCanvaskit,
'vmserviceOutFile': vmserviceOutFile, 'vmserviceOutFile': vmserviceOutFile,
'fastStart': fastStart, 'fastStart': fastStart,
'nullAssertions': nullAssertions, 'nullAssertions': nullAssertions,
@ -1365,6 +1372,7 @@ class DebuggingOptions {
webLaunchUrl: json['webLaunchUrl'] as String?, webLaunchUrl: json['webLaunchUrl'] as String?,
webRenderer: WebRendererMode.values.byName(json['webRenderer']! as String), webRenderer: WebRendererMode.values.byName(json['webRenderer']! as String),
webUseWasm: json['webUseWasm']! as bool, webUseWasm: json['webUseWasm']! as bool,
webUseLocalCanvaskit: json['webUseLocalCanvaskit']! as bool,
vmserviceOutFile: json['vmserviceOutFile'] as String?, vmserviceOutFile: json['vmserviceOutFile'] as String?,
fastStart: json['fastStart']! as bool, fastStart: json['fastStart']! as bool,
nullAssertions: json['nullAssertions']! as bool, nullAssertions: json['nullAssertions']! as bool,

View File

@ -79,7 +79,8 @@ class WebDriverService extends DriverService {
port: debuggingOptions.port, port: debuggingOptions.port,
hostname: debuggingOptions.hostname, hostname: debuggingOptions.hostname,
webRenderer: debuggingOptions.webRenderer, webRenderer: debuggingOptions.webRenderer,
webUseWasm: debuggingOptions.webUseWasm webUseWasm: debuggingOptions.webUseWasm,
webUseLocalCanvaskit: debuggingOptions.webUseLocalCanvaskit,
) )
: DebuggingOptions.enabled( : DebuggingOptions.enabled(
buildInfo, buildInfo,
@ -88,6 +89,7 @@ class WebDriverService extends DriverService {
disablePortPublication: debuggingOptions.disablePortPublication, disablePortPublication: debuggingOptions.disablePortPublication,
webRenderer: debuggingOptions.webRenderer, webRenderer: debuggingOptions.webRenderer,
webUseWasm: debuggingOptions.webUseWasm, webUseWasm: debuggingOptions.webUseWasm,
webUseLocalCanvaskit: debuggingOptions.webUseLocalCanvaskit,
), ),
stayResident: true, stayResident: true,
flutterProject: FlutterProject.current(), flutterProject: FlutterProject.current(),

View File

@ -120,6 +120,7 @@ class WebAssetServer implements AssetReader {
this._nullSafetyMode, this._nullSafetyMode,
this._ddcModuleSystem, { this._ddcModuleSystem, {
required this.webRenderer, required this.webRenderer,
required this.useLocalCanvasKit,
}) : basePath = _getWebTemplate('index.html', _kDefaultIndex).getBaseHref(); }) : basePath = _getWebTemplate('index.html', _kDefaultIndex).getBaseHref();
// Fallback to "application/octet-stream" on null which // Fallback to "application/octet-stream" on null which
@ -181,6 +182,7 @@ class WebAssetServer implements AssetReader {
NullSafetyMode nullSafetyMode, { NullSafetyMode nullSafetyMode, {
required WebRendererMode webRenderer, required WebRendererMode webRenderer,
required bool isWasm, required bool isWasm,
required bool useLocalCanvasKit,
bool testMode = false, bool testMode = false,
DwdsLauncher dwdsLauncher = Dwds.start, DwdsLauncher dwdsLauncher = Dwds.start,
// TODO(markzipan): Make sure this default value aligns with that in the debugger options. // TODO(markzipan): Make sure this default value aligns with that in the debugger options.
@ -233,6 +235,7 @@ class WebAssetServer implements AssetReader {
nullSafetyMode, nullSafetyMode,
ddcModuleSystem, ddcModuleSystem,
webRenderer: webRenderer, webRenderer: webRenderer,
useLocalCanvasKit: useLocalCanvasKit,
); );
if (testMode) { if (testMode) {
return server; return server;
@ -530,6 +533,8 @@ class WebAssetServer implements AssetReader {
/// Determines what rendering backed to use. /// Determines what rendering backed to use.
final WebRendererMode webRenderer; final WebRendererMode webRenderer;
final bool useLocalCanvasKit;
String get _buildConfigString { String get _buildConfigString {
final Map<String, dynamic> buildConfig = <String, dynamic>{ final Map<String, dynamic> buildConfig = <String, dynamic>{
'engineRevision': globals.flutterVersion.engineRevision, 'engineRevision': globals.flutterVersion.engineRevision,
@ -540,6 +545,7 @@ class WebAssetServer implements AssetReader {
'mainJsPath': 'main.dart.js', 'mainJsPath': 'main.dart.js',
}, },
], ],
if (useLocalCanvasKit) 'useLocalCanvasKit' : true,
}; };
return ''' return '''
if (!window._flutter) { if (!window._flutter) {
@ -740,6 +746,7 @@ class WebDevFS implements DevFS {
required this.ddcModuleSystem, required this.ddcModuleSystem,
required this.webRenderer, required this.webRenderer,
required this.isWasm, required this.isWasm,
required this.useLocalCanvasKit,
required this.rootDirectory, required this.rootDirectory,
this.testMode = false, this.testMode = false,
}) : _port = port; }) : _port = port;
@ -767,6 +774,7 @@ class WebDevFS implements DevFS {
final String? tlsCertKeyPath; final String? tlsCertKeyPath;
final WebRendererMode webRenderer; final WebRendererMode webRenderer;
final bool isWasm; final bool isWasm;
final bool useLocalCanvasKit;
late WebAssetServer webAssetServer; late WebAssetServer webAssetServer;
@ -868,6 +876,7 @@ class WebDevFS implements DevFS {
nullSafetyMode, nullSafetyMode,
webRenderer: webRenderer, webRenderer: webRenderer,
isWasm: isWasm, isWasm: isWasm,
useLocalCanvasKit: useLocalCanvasKit,
testMode: testMode, testMode: testMode,
ddcModuleSystem: ddcModuleSystem, ddcModuleSystem: ddcModuleSystem,
); );

View File

@ -318,6 +318,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
ddcModuleSystem: debuggingOptions.buildInfo.ddcModuleFormat == DdcModuleFormat.ddc, ddcModuleSystem: debuggingOptions.buildInfo.ddcModuleFormat == DdcModuleFormat.ddc,
webRenderer: debuggingOptions.webRenderer, webRenderer: debuggingOptions.webRenderer,
isWasm: debuggingOptions.webUseWasm, isWasm: debuggingOptions.webUseWasm,
useLocalCanvasKit: debuggingOptions.webUseLocalCanvaskit,
rootDirectory: fileSystem.directory(projectRootPath), rootDirectory: fileSystem.directory(projectRootPath),
); );
Uri url = await device!.devFS!.create(); Uri url = await device!.devFS!.create();

View File

@ -1281,16 +1281,11 @@ abstract class FlutterCommand extends Command<void> {
final Map<String, Object?> defineConfigJsonMap = extractDartDefineConfigJsonMap(); final Map<String, Object?> defineConfigJsonMap = extractDartDefineConfigJsonMap();
final List<String> dartDefines = extractDartDefines(defineConfigJsonMap: defineConfigJsonMap); final List<String> dartDefines = extractDartDefines(defineConfigJsonMap: defineConfigJsonMap);
final bool useCdn = !argParser.options.containsKey(FlutterOptions.kWebResourcesCdnFlag)
if (argParser.options.containsKey(FlutterOptions.kWebResourcesCdnFlag)) { || boolArg(FlutterOptions.kWebResourcesCdnFlag);
final bool hasLocalWebSdk = argParser.options.containsKey('local-web-sdk') && stringArg('local-web-sdk') != null; final bool useLocalWebSdk = argParser.options.containsKey(FlutterGlobalOptions.kLocalWebSDKOption)
if (boolArg(FlutterOptions.kWebResourcesCdnFlag) && !hasLocalWebSdk) { && stringArg(FlutterGlobalOptions.kLocalWebSDKOption, global: true) != null;
if (!dartDefines.any((String define) => define.startsWith('FLUTTER_WEB_CANVASKIT_URL='))) { final bool useLocalCanvasKit = !useCdn || useLocalWebSdk;
dartDefines.add('FLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/${globals.flutterVersion.engineRevision}/');
}
}
}
final String? defaultFlavor = FlutterProject.current().manifest.defaultFlavor; final String? defaultFlavor = FlutterProject.current().manifest.defaultFlavor;
final String? cliFlavor = argParser.options.containsKey('flavor') ? stringArg('flavor') : null; final String? cliFlavor = argParser.options.containsKey('flavor') ? stringArg('flavor') : null;
final String? flavor = cliFlavor ?? defaultFlavor; final String? flavor = cliFlavor ?? defaultFlavor;
@ -1343,6 +1338,7 @@ abstract class FlutterCommand extends Command<void> {
: null, : null,
assumeInitializeFromDillUpToDate: argParser.options.containsKey(FlutterOptions.kAssumeInitializeFromDillUpToDate) assumeInitializeFromDillUpToDate: argParser.options.containsKey(FlutterOptions.kAssumeInitializeFromDillUpToDate)
&& boolArg(FlutterOptions.kAssumeInitializeFromDillUpToDate), && boolArg(FlutterOptions.kAssumeInitializeFromDillUpToDate),
useLocalCanvasKit: useLocalCanvasKit,
); );
} }

View File

@ -72,15 +72,15 @@ class WebTemplate {
return <WebTemplateWarning>[ return <WebTemplateWarning>[
..._getWarningsForPattern( ..._getWarningsForPattern(
RegExp('(const|var) serviceWorkerVersion = null'), RegExp('(const|var) serviceWorkerVersion = null'),
'Local variable for "serviceWorkerVersion" is deprecated. Use "{{flutter_service_worker_version}}" template token instead.', 'Local variable for "serviceWorkerVersion" is deprecated. Use "{{flutter_service_worker_version}}" template token instead. See https://docs.flutter.dev/platform-integration/web/initialization for more details.',
), ),
..._getWarningsForPattern( ..._getWarningsForPattern(
"navigator.serviceWorker.register('flutter_service_worker.js')", "navigator.serviceWorker.register('flutter_service_worker.js')",
'Manual service worker registration deprecated. Use flutter.js service worker bootstrapping instead.', 'Manual service worker registration deprecated. Use flutter.js service worker bootstrapping instead. See https://docs.flutter.dev/platform-integration/web/initialization for more details.',
), ),
..._getWarningsForPattern( ..._getWarningsForPattern(
'_flutter.loader.loadEntrypoint(', '_flutter.loader.loadEntrypoint(',
'"FlutterLoader.loadEntrypoint" is deprecated. Use "FlutterLoader.load" instead.', '"FlutterLoader.loadEntrypoint" is deprecated. Use "FlutterLoader.load" instead. See https://docs.flutter.dev/platform-integration/web/initialization for more details.',
), ),
]; ];
} }

View File

@ -156,6 +156,7 @@ void main() {
'DartObfuscation': 'false', 'DartObfuscation': 'false',
'TrackWidgetCreation': 'false', 'TrackWidgetCreation': 'false',
'TreeShakeIcons': 'true', 'TreeShakeIcons': 'true',
'UseLocalCanvasKit': 'true',
}); });
}), }),
}); });
@ -252,6 +253,7 @@ void main() {
'DartObfuscation': 'false', 'DartObfuscation': 'false',
'TrackWidgetCreation': 'false', 'TrackWidgetCreation': 'false',
'TreeShakeIcons': 'true', 'TreeShakeIcons': 'true',
'UseLocalCanvasKit': 'true',
}); });
}), }),
}); });
@ -338,22 +340,6 @@ void main() {
BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)), BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)),
}); });
testUsingContext('Defaults to gstatic CanvasKit artifacts', () async {
final TestWebBuildCommand buildCommand = TestWebBuildCommand(fileSystem: fileSystem);
final CommandRunner<void> runner = createTestCommandRunner(buildCommand);
setupFileSystemForEndToEndTest(fileSystem);
await runner.run(<String>['build', 'web', '--no-pub', '--web-resources-cdn']);
final BuildInfo buildInfo =
await buildCommand.webCommand.getBuildInfo(forcedBuildMode: BuildMode.debug);
expect(buildInfo.dartDefines, contains(startsWith('FLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/')));
}, overrides: <Type, Generator>{
Platform: () => fakePlatform,
FileSystem: () => fileSystem,
FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
ProcessManager: () => processManager,
BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)),
});
testUsingContext('Does not override custom CanvasKit URL', () async { testUsingContext('Does not override custom CanvasKit URL', () async {
final TestWebBuildCommand buildCommand = TestWebBuildCommand(fileSystem: fileSystem); final TestWebBuildCommand buildCommand = TestWebBuildCommand(fileSystem: fileSystem);
final CommandRunner<void> runner = createTestCommandRunner(buildCommand); final CommandRunner<void> runner = createTestCommandRunner(buildCommand);

View File

@ -144,11 +144,24 @@ void main() {
<!DOCTYPE html><html><base href="$kBaseHrefPlaceholder"><head></head></html> <!DOCTYPE html><html><base href="$kBaseHrefPlaceholder"><head></head></html>
'''); ''');
environment.buildDir.childFile('main.dart.js').createSync(); environment.buildDir.childFile('main.dart.js').createSync();
await WebTemplatedFiles('buildConfig').build(environment); await WebTemplatedFiles(<Map<String, Object?>>[]).build(environment);
expect(environment.outputDir.childFile('index.html').readAsStringSync(), contains('/basehreftest/')); expect(environment.outputDir.childFile('index.html').readAsStringSync(), contains('/basehreftest/'));
})); }));
test('WebTemplatedFiles emits useLocalCanvasKit in flutter_bootstrap.js when environment specifies', () => testbed.run(() async {
environment.defines[kUseLocalCanvasKitFlag] = 'true';
final Directory webResources = environment.projectDir.childDirectory('web');
webResources.childFile('index.html').createSync(recursive: true);
webResources.childFile('index.html').writeAsStringSync('''
<!DOCTYPE html><html><base href="$kBaseHrefPlaceholder"><head></head></html>
''');
environment.buildDir.childFile('main.dart.js').createSync();
await WebTemplatedFiles(<Map<String, Object?>>[]).build(environment);
expect(environment.outputDir.childFile('flutter_bootstrap.js').readAsStringSync(), contains('"useLocalCanvasKit":true'));
}));
test('null base href does not override existing base href in index.html', () => testbed.run(() async { test('null base href does not override existing base href in index.html', () => testbed.run(() async {
environment.defines[kBuildMode] = 'release'; environment.defines[kBuildMode] = 'release';
final Directory webResources = environment.projectDir.childDirectory('web'); final Directory webResources = environment.projectDir.childDirectory('web');
@ -157,7 +170,7 @@ void main() {
<!DOCTYPE html><html><head><base href='/basehreftest/'></head></html> <!DOCTYPE html><html><head><base href='/basehreftest/'></head></html>
'''); ''');
environment.buildDir.childFile('main.dart.js').createSync(); environment.buildDir.childFile('main.dart.js').createSync();
await WebTemplatedFiles('build config').build(environment); await WebTemplatedFiles(<Map<String, Object?>>[]).build(environment);
expect(environment.outputDir.childFile('index.html').readAsStringSync(), contains('/basehreftest/')); expect(environment.outputDir.childFile('index.html').readAsStringSync(), contains('/basehreftest/'));
})); }));
@ -378,6 +391,7 @@ void main() {
'-Ddart.vm.profile=true', '-Ddart.vm.profile=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-source-maps', '--no-source-maps',
'-o', '-o',
environment.buildDir.childFile('app.dill').absolute.path, environment.buildDir.childFile('app.dill').absolute.path,
@ -392,6 +406,7 @@ void main() {
'-Ddart.vm.profile=true', '-Ddart.vm.profile=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-minify', '--no-minify',
'--no-source-maps', '--no-source-maps',
'-O4', '-O4',
@ -421,6 +436,7 @@ void main() {
'-Ddart.vm.profile=true', '-Ddart.vm.profile=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-source-maps', '--no-source-maps',
'-o', '-o',
environment.buildDir.childFile('app.dill').absolute.path, environment.buildDir.childFile('app.dill').absolute.path,
@ -435,6 +451,7 @@ void main() {
'-Ddart.vm.profile=true', '-Ddart.vm.profile=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-minify', '--no-minify',
'--no-source-maps', '--no-source-maps',
'-O4', '-O4',
@ -463,6 +480,7 @@ void main() {
'-Ddart.vm.profile=true', '-Ddart.vm.profile=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-source-maps', '--no-source-maps',
'-o', '-o',
environment.buildDir.childFile('app.dill').absolute.path, environment.buildDir.childFile('app.dill').absolute.path,
@ -478,6 +496,7 @@ void main() {
'-Ddart.vm.profile=true', '-Ddart.vm.profile=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-minify', '--no-minify',
'--no-source-maps', '--no-source-maps',
'-O4', '-O4',
@ -504,6 +523,7 @@ void main() {
'-Ddart.vm.profile=true', '-Ddart.vm.profile=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-source-maps', '--no-source-maps',
'-o', '-o',
environment.buildDir.childFile('app.dill').absolute.path, environment.buildDir.childFile('app.dill').absolute.path,
@ -518,6 +538,7 @@ void main() {
'-Ddart.vm.profile=true', '-Ddart.vm.profile=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-minify', '--no-minify',
'--no-source-maps', '--no-source-maps',
'-O4', '-O4',
@ -544,6 +565,7 @@ void main() {
'-Ddart.vm.product=true', '-Ddart.vm.product=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-source-maps', '--no-source-maps',
'-o', '-o',
environment.buildDir.childFile('app.dill').absolute.path, environment.buildDir.childFile('app.dill').absolute.path,
@ -558,6 +580,7 @@ void main() {
'-Ddart.vm.product=true', '-Ddart.vm.product=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-source-maps', '--no-source-maps',
'-O4', '-O4',
'-o', '-o',
@ -584,6 +607,7 @@ void main() {
'-Ddart.vm.product=true', '-Ddart.vm.product=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--native-null-assertions', '--native-null-assertions',
'--no-source-maps', '--no-source-maps',
'-o', '-o',
@ -599,6 +623,7 @@ void main() {
'-Ddart.vm.product=true', '-Ddart.vm.product=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--native-null-assertions', '--native-null-assertions',
'--no-source-maps', '--no-source-maps',
'-O4', '-O4',
@ -626,6 +651,7 @@ void main() {
'-Ddart.vm.product=true', '-Ddart.vm.product=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-source-maps', '--no-source-maps',
'-o', '-o',
environment.buildDir.childFile('app.dill').absolute.path, environment.buildDir.childFile('app.dill').absolute.path,
@ -640,6 +666,7 @@ void main() {
'-Ddart.vm.product=true', '-Ddart.vm.product=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-source-maps', '--no-source-maps',
'-O3', '-O3',
'-o', '-o',
@ -666,6 +693,7 @@ void main() {
'-Ddart.vm.product=true', '-Ddart.vm.product=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-source-maps', '--no-source-maps',
'-o', '-o',
environment.buildDir.childFile('app.dill').absolute.path, environment.buildDir.childFile('app.dill').absolute.path,
@ -683,6 +711,7 @@ void main() {
'-Ddart.vm.product=true', '-Ddart.vm.product=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-source-maps', '--no-source-maps',
'-O4', '-O4',
'-o', '-o',
@ -718,6 +747,7 @@ void main() {
'-DBAZ=qux', '-DBAZ=qux',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-source-maps', '--no-source-maps',
'-o', '-o',
environment.buildDir.childFile('app.dill').absolute.path, environment.buildDir.childFile('app.dill').absolute.path,
@ -734,6 +764,7 @@ void main() {
'-DBAZ=qux', '-DBAZ=qux',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-source-maps', '--no-source-maps',
'-O4', '-O4',
'-o', '-o',
@ -760,6 +791,7 @@ void main() {
'-Ddart.vm.product=true', '-Ddart.vm.product=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'-o', '-o',
environment.buildDir.childFile('app.dill').absolute.path, environment.buildDir.childFile('app.dill').absolute.path,
'--packages=.dart_tool/package_config.json', '--packages=.dart_tool/package_config.json',
@ -773,6 +805,7 @@ void main() {
'-Ddart.vm.product=true', '-Ddart.vm.product=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'-O4', '-O4',
'-o', '-o',
environment.buildDir.childFile('main.dart.js').absolute.path, environment.buildDir.childFile('main.dart.js').absolute.path,
@ -799,6 +832,7 @@ void main() {
'-DBAZ=qux', '-DBAZ=qux',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-source-maps', '--no-source-maps',
'-o', '-o',
environment.buildDir.childFile('app.dill').absolute.path, environment.buildDir.childFile('app.dill').absolute.path,
@ -815,6 +849,7 @@ void main() {
'-DBAZ=qux', '-DBAZ=qux',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-minify', '--no-minify',
'--no-source-maps', '--no-source-maps',
'-O4', '-O4',
@ -842,6 +877,7 @@ void main() {
'-Ddart.vm.profile=true', '-Ddart.vm.profile=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-source-maps', '--no-source-maps',
'-o', '-o',
environment.buildDir.childFile('app.dill').absolute.path, environment.buildDir.childFile('app.dill').absolute.path,
@ -856,6 +892,7 @@ void main() {
'-Ddart.vm.profile=true', '-Ddart.vm.profile=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-minify', '--no-minify',
'--no-source-maps', '--no-source-maps',
'-O4', '-O4',
@ -885,6 +922,7 @@ void main() {
'-Ddart.vm.profile=true', '-Ddart.vm.profile=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-source-maps', '--no-source-maps',
'-o', '-o',
environment.buildDir.childFile('app.dill').absolute.path, environment.buildDir.childFile('app.dill').absolute.path,
@ -899,6 +937,7 @@ void main() {
'-Ddart.vm.profile=true', '-Ddart.vm.profile=true',
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--no-minify', '--no-minify',
'--no-source-maps', '--no-source-maps',
'-O4', '-O4',
@ -949,6 +988,7 @@ void main() {
'-DFLUTTER_WEB_AUTO_DETECT=false', '-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true', '-DFLUTTER_WEB_USE_SKIA=true',
], ],
'-DFLUTTER_WEB_CANVASKIT_URL=https://www.gstatic.com/flutter-canvaskit/abcdefghijklmnopqrstuvwxyz/',
'--extra-compiler-option=--depfile=${depFile.absolute.path}', '--extra-compiler-option=--depfile=${depFile.absolute.path}',
'-O$level', '-O$level',
if (strip && buildMode == 'release') '--strip-wasm' else '--no-strip-wasm', if (strip && buildMode == 'release') '--strip-wasm' else '--no-strip-wasm',

View File

@ -130,6 +130,7 @@ void main() {
NullSafetyMode.unsound, NullSafetyMode.unsound,
usesDdcModuleSystem, usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
); );
releaseAssetServer = ReleaseAssetServer( releaseAssetServer = ReleaseAssetServer(
globals.fs.file('main.dart').uri, globals.fs.file('main.dart').uri,
@ -414,6 +415,7 @@ void main() {
NullSafetyMode.unsound, NullSafetyMode.unsound,
usesDdcModuleSystem, usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
); );
expect(webAssetServer.basePath, 'foo/bar'); expect(webAssetServer.basePath, 'foo/bar');
@ -437,6 +439,7 @@ void main() {
NullSafetyMode.unsound, NullSafetyMode.unsound,
usesDdcModuleSystem, usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
); );
// Defaults to "/" when there's no base element. // Defaults to "/" when there's no base element.
@ -462,6 +465,7 @@ void main() {
NullSafetyMode.unsound, NullSafetyMode.unsound,
usesDdcModuleSystem, usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
), ),
throwsToolExit(), throwsToolExit(),
); );
@ -486,6 +490,7 @@ void main() {
NullSafetyMode.unsound, NullSafetyMode.unsound,
usesDdcModuleSystem, usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
), ),
throwsToolExit(), throwsToolExit(),
); );
@ -929,6 +934,7 @@ void main() {
ddcModuleSystem: usesDdcModuleSystem, ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.html, webRenderer: WebRendererMode.html,
isWasm: false, isWasm: false,
useLocalCanvasKit: false,
rootDirectory: globals.fs.currentDirectory, rootDirectory: globals.fs.currentDirectory,
); );
webDevFS.ddcModuleLoaderJS.createSync(recursive: true); webDevFS.ddcModuleLoaderJS.createSync(recursive: true);
@ -1066,6 +1072,7 @@ void main() {
ddcModuleSystem: usesDdcModuleSystem, ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.html, webRenderer: WebRendererMode.html,
isWasm: false, isWasm: false,
useLocalCanvasKit: false,
rootDirectory: globals.fs.currentDirectory, rootDirectory: globals.fs.currentDirectory,
); );
webDevFS.ddcModuleLoaderJS.createSync(recursive: true); webDevFS.ddcModuleLoaderJS.createSync(recursive: true);
@ -1203,6 +1210,7 @@ void main() {
ddcModuleSystem: usesDdcModuleSystem, ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
isWasm: false, isWasm: false,
useLocalCanvasKit: false,
rootDirectory: globals.fs.currentDirectory, rootDirectory: globals.fs.currentDirectory,
); );
webDevFS.ddcModuleLoaderJS.createSync(recursive: true); webDevFS.ddcModuleLoaderJS.createSync(recursive: true);
@ -1277,6 +1285,7 @@ void main() {
ddcModuleSystem: usesDdcModuleSystem, ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
isWasm: false, isWasm: false,
useLocalCanvasKit: false,
rootDirectory: globals.fs.currentDirectory, rootDirectory: globals.fs.currentDirectory,
); );
webDevFS.ddcModuleLoaderJS.createSync(recursive: true); webDevFS.ddcModuleLoaderJS.createSync(recursive: true);
@ -1327,6 +1336,7 @@ void main() {
ddcModuleSystem: usesDdcModuleSystem, ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
isWasm: false, isWasm: false,
useLocalCanvasKit: false,
rootDirectory: globals.fs.currentDirectory, rootDirectory: globals.fs.currentDirectory,
); );
webDevFS.ddcModuleLoaderJS.createSync(recursive: true); webDevFS.ddcModuleLoaderJS.createSync(recursive: true);
@ -1379,6 +1389,7 @@ void main() {
ddcModuleSystem: usesDdcModuleSystem, ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.auto, webRenderer: WebRendererMode.auto,
isWasm: false, isWasm: false,
useLocalCanvasKit: false,
rootDirectory: globals.fs.currentDirectory, rootDirectory: globals.fs.currentDirectory,
); );
webDevFS.ddcModuleLoaderJS.createSync(recursive: true); webDevFS.ddcModuleLoaderJS.createSync(recursive: true);
@ -1433,6 +1444,7 @@ void main() {
ddcModuleSystem: usesDdcModuleSystem, ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
isWasm: false, isWasm: false,
useLocalCanvasKit: false,
rootDirectory: globals.fs.currentDirectory, rootDirectory: globals.fs.currentDirectory,
); );
webDevFS.ddcModuleLoaderJS.createSync(recursive: true); webDevFS.ddcModuleLoaderJS.createSync(recursive: true);
@ -1472,6 +1484,7 @@ void main() {
NullSafetyMode.unsound, NullSafetyMode.unsound,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
isWasm: false, isWasm: false,
useLocalCanvasKit: false,
testMode: true); testMode: true);
expect(webAssetServer.defaultResponseHeaders['x-frame-options'], null); expect(webAssetServer.defaultResponseHeaders['x-frame-options'], null);
@ -1506,6 +1519,7 @@ void main() {
NullSafetyMode.unsound, NullSafetyMode.unsound,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
isWasm: false, isWasm: false,
useLocalCanvasKit: false,
testMode: true); testMode: true);
expect(webAssetServer.defaultResponseHeaders[extraHeaderKey], expect(webAssetServer.defaultResponseHeaders[extraHeaderKey],
@ -1551,6 +1565,7 @@ void main() {
NullSafetyMode.sound, NullSafetyMode.sound,
usesDdcModuleSystem, usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
); );
expect( expect(
@ -1607,6 +1622,7 @@ void main() {
ddcModuleSystem: usesDdcModuleSystem, ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
isWasm: false, isWasm: false,
useLocalCanvasKit: false,
rootDirectory: globals.fs.currentDirectory, rootDirectory: globals.fs.currentDirectory,
); );
webDevFS.ddcModuleLoaderJS.createSync(recursive: true); webDevFS.ddcModuleLoaderJS.createSync(recursive: true);

View File

@ -69,6 +69,7 @@ void main() {
NullSafetyMode.unsound, NullSafetyMode.unsound,
usesDdcModuleSystem, usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
); );
releaseAssetServer = ReleaseAssetServer( releaseAssetServer = ReleaseAssetServer(
globals.fs.file('main.dart').uri, globals.fs.file('main.dart').uri,
@ -306,6 +307,7 @@ void main() {
NullSafetyMode.unsound, NullSafetyMode.unsound,
usesDdcModuleSystem, usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
); );
expect(webAssetServer.basePath, 'foo/bar'); expect(webAssetServer.basePath, 'foo/bar');
@ -327,6 +329,7 @@ void main() {
NullSafetyMode.unsound, NullSafetyMode.unsound,
usesDdcModuleSystem, usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
); );
// Defaults to "/" when there's no base element. // Defaults to "/" when there's no base element.
@ -350,6 +353,7 @@ void main() {
NullSafetyMode.unsound, NullSafetyMode.unsound,
usesDdcModuleSystem, usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
), ),
throwsToolExit(), throwsToolExit(),
); );
@ -372,6 +376,7 @@ void main() {
NullSafetyMode.unsound, NullSafetyMode.unsound,
usesDdcModuleSystem, usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
), ),
throwsToolExit(), throwsToolExit(),
); );
@ -392,6 +397,48 @@ void main() {
expect((await response.read().toList()).first, utf8.encode('main() {}')); expect((await response.read().toList()).first, utf8.encode('main() {}'));
})); }));
test('serves flutter_bootstrap.js without useLocalCanvasKit', () => testbed.run(() async {
globals.fs.file(globals.fs.path.join(
globals.artifacts!.getHostArtifact(HostArtifact.flutterJsDirectory).path,
'flutter.js',
))..createSync(recursive: true)..writeAsStringSync('flutter.js content');
final Response response = await webAssetServer.handleRequest(
Request('GET', Uri.parse('http://foobar/flutter_bootstrap.js'))
);
expect(response.statusCode, 200);
final String body = await response.readAsString();
expect(body, isNot(contains('useLocalCanvasKit')));
}));
test('serves flutter_bootstrap.js with useLocalCanvasKit', () => testbed.run(() async {
globals.fs.file(globals.fs.path.join(
globals.artifacts!.getHostArtifact(HostArtifact.flutterJsDirectory).path,
'flutter.js',
))..createSync(recursive: true)..writeAsStringSync('flutter.js content');
webAssetServer = WebAssetServer(
httpServer,
packages,
InternetAddress.loopbackIPv4,
<String, String>{},
<String, String>{},
NullSafetyMode.unsound,
usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: true,
);
final Response response = await webAssetServer.handleRequest(
Request('GET', Uri.parse('http://foobar/flutter_bootstrap.js'))
);
expect(response.statusCode, 200);
final String body = await response.readAsString();
expect(body, contains('"useLocalCanvasKit":true'));
}));
test('Returns notModified when the ifNoneMatch header matches the etag', () => testbed.run(() async { test('Returns notModified when the ifNoneMatch header matches the etag', () => testbed.run(() async {
webAssetServer.writeFile('foo.js', 'main() {}'); webAssetServer.writeFile('foo.js', 'main() {}');
@ -717,6 +764,7 @@ void main() {
ddcModuleSystem: usesDdcModuleSystem, ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.html, webRenderer: WebRendererMode.html,
isWasm: false, isWasm: false,
useLocalCanvasKit: false,
rootDirectory: globals.fs.currentDirectory, rootDirectory: globals.fs.currentDirectory,
); );
webDevFS.requireJS.createSync(recursive: true); webDevFS.requireJS.createSync(recursive: true);
@ -830,6 +878,7 @@ void main() {
ddcModuleSystem: usesDdcModuleSystem, ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.html, webRenderer: WebRendererMode.html,
isWasm: false, isWasm: false,
useLocalCanvasKit: false,
rootDirectory: globals.fs.currentDirectory, rootDirectory: globals.fs.currentDirectory,
); );
webDevFS.requireJS.createSync(recursive: true); webDevFS.requireJS.createSync(recursive: true);
@ -949,6 +998,7 @@ void main() {
ddcModuleSystem: usesDdcModuleSystem, ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
isWasm: false, isWasm: false,
useLocalCanvasKit: false,
rootDirectory: globals.fs.currentDirectory, rootDirectory: globals.fs.currentDirectory,
); );
webDevFS.requireJS.createSync(recursive: true); webDevFS.requireJS.createSync(recursive: true);
@ -1014,6 +1064,7 @@ void main() {
ddcModuleSystem: usesDdcModuleSystem, ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
isWasm: false, isWasm: false,
useLocalCanvasKit: false,
rootDirectory: globals.fs.currentDirectory, rootDirectory: globals.fs.currentDirectory,
); );
webDevFS.requireJS.createSync(recursive: true); webDevFS.requireJS.createSync(recursive: true);
@ -1063,6 +1114,7 @@ void main() {
ddcModuleSystem: usesDdcModuleSystem, ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
isWasm: false, isWasm: false,
useLocalCanvasKit: false,
rootDirectory: globals.fs.currentDirectory, rootDirectory: globals.fs.currentDirectory,
); );
webDevFS.requireJS.createSync(recursive: true); webDevFS.requireJS.createSync(recursive: true);
@ -1113,6 +1165,7 @@ void main() {
ddcModuleSystem: usesDdcModuleSystem, ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.auto, webRenderer: WebRendererMode.auto,
isWasm: false, isWasm: false,
useLocalCanvasKit: false,
rootDirectory: globals.fs.currentDirectory, rootDirectory: globals.fs.currentDirectory,
); );
webDevFS.requireJS.createSync(recursive: true); webDevFS.requireJS.createSync(recursive: true);
@ -1164,6 +1217,7 @@ void main() {
ddcModuleSystem: usesDdcModuleSystem, ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
isWasm: false, isWasm: false,
useLocalCanvasKit: false,
rootDirectory: globals.fs.currentDirectory, rootDirectory: globals.fs.currentDirectory,
); );
webDevFS.requireJS.createSync(recursive: true); webDevFS.requireJS.createSync(recursive: true);
@ -1203,6 +1257,7 @@ void main() {
NullSafetyMode.unsound, NullSafetyMode.unsound,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
isWasm: false, isWasm: false,
useLocalCanvasKit: false,
testMode: true testMode: true
); );
@ -1238,6 +1293,7 @@ void main() {
NullSafetyMode.unsound, NullSafetyMode.unsound,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
isWasm: false, isWasm: false,
useLocalCanvasKit: false,
testMode: true testMode: true
); );
@ -1276,6 +1332,7 @@ void main() {
NullSafetyMode.sound, NullSafetyMode.sound,
usesDdcModuleSystem, usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
); );
expect(await webAssetServer.metadataContents('foo/main_module.ddc_merged_metadata'), null); expect(await webAssetServer.metadataContents('foo/main_module.ddc_merged_metadata'), null);
@ -1321,6 +1378,7 @@ void main() {
ddcModuleSystem: usesDdcModuleSystem, ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit, webRenderer: WebRendererMode.canvaskit,
isWasm: false, isWasm: false,
useLocalCanvasKit: false,
rootDirectory: globals.fs.currentDirectory, rootDirectory: globals.fs.currentDirectory,
); );
webDevFS.requireJS.createSync(recursive: true); webDevFS.requireJS.createSync(recursive: true);