From 2efeeb47bc246d8b1176c836080b936d3241b5ea Mon Sep 17 00:00:00 2001 From: Jackson Gardner Date: Thu, 8 Feb 2024 13:45:09 -0800 Subject: [PATCH] Revert Dual Web Compile changes (#143175) Dual Web Compile has had some issues where `flutter test` is not respecting the `--web-renderer` flag for some reason. I haven't gotten entirely to the bottom of the issue, but for now we need to rever these changes while I investigate. This reverts the following PRs: https://github.com/flutter/flutter/pull/143128 https://github.com/flutter/flutter/pull/141396 While doing this revert, I had a few merge conflicts with https://github.com/flutter/flutter/pull/142760, and I tried to resolve the merge conflicts within the spirit of that PR's change, but @chingjun I might need your input on whether the imports I have modified are okay with regards to the change you were making. --- dev/benchmarks/macrobenchmarks/web/index.html | 6 +- dev/devicelab/lib/tasks/web_benchmarks.dart | 4 +- .../web_e2e_tests/web/index.html | 17 +- .../flutter_tools/lib/src/build_info.dart | 13 +- .../lib/src/build_system/build_system.dart | 146 +++-------- .../lib/src/build_system/build_targets.dart | 14 +- .../lib/src/build_system/targets/web.dart | 164 +++++------- .../lib/src/commands/build_web.dart | 40 +-- .../flutter_tools/lib/src/commands/run.dart | 7 - .../flutter_tools/lib/src/commands/test.dart | 6 - packages/flutter_tools/lib/src/device.dart | 9 - .../lib/src/drive/web_driver_service.dart | 2 - .../flutter_tools/lib/src/html_utils.dart | 7 - .../lib/src/isolated/build_targets.dart | 9 +- .../lib/src/isolated/devfs_web.dart | 30 +-- .../lib/src/isolated/resident_web_runner.dart | 15 +- .../lib/src/resident_runner.dart | 2 +- .../lib/src/runner/flutter_command.dart | 22 +- .../lib/src/test/web_test_compiler.dart | 2 +- .../flutter_tools/lib/src/web/compile.dart | 46 ++-- .../lib/src/web/compiler_config.dart | 145 ++++++----- .../hermetic/build_web_test.dart | 27 +- .../commands.shard/hermetic/run_test.dart | 42 ++++ .../commands.shard/hermetic/test_test.dart | 19 -- .../build_system/build_system_test.dart | 41 +-- .../targets/web_defines_test.dart | 51 ---- .../build_system/targets/web_test.dart | 235 ++++-------------- .../general.shard/web/compile_web_test.dart | 33 ++- .../general.shard/web/devfs_web_test.dart | 34 ++- .../flutter_build_wasm_test.dart | 2 +- .../test/web.shard/hot_reload_web_test.dart | 1 - .../hot_reload_index_html_samples.dart | 21 -- 32 files changed, 416 insertions(+), 796 deletions(-) delete mode 100644 packages/flutter_tools/test/general.shard/build_system/targets/web_defines_test.dart diff --git a/dev/benchmarks/macrobenchmarks/web/index.html b/dev/benchmarks/macrobenchmarks/web/index.html index f73aee43082..dec5a5150c7 100644 --- a/dev/benchmarks/macrobenchmarks/web/index.html +++ b/dev/benchmarks/macrobenchmarks/web/index.html @@ -6,12 +6,8 @@ found in the LICENSE file. --> Web Benchmarks - - + diff --git a/dev/devicelab/lib/tasks/web_benchmarks.dart b/dev/devicelab/lib/tasks/web_benchmarks.dart index 031d478fcfa..a4748b8f9f8 100644 --- a/dev/devicelab/lib/tasks/web_benchmarks.dart +++ b/dev/devicelab/lib/tasks/web_benchmarks.dart @@ -39,7 +39,7 @@ Future runWebBenchmark(WebBenchmarkOptions benchmarkOptions) async { '--omit-type-checks', ], '--dart-define=FLUTTER_WEB_ENABLE_PROFILING=true', - if (!benchmarkOptions.useWasm) '--web-renderer=${benchmarkOptions.webRenderer}', + '--web-renderer=${benchmarkOptions.webRenderer}', '--profile', '--no-web-resources-cdn', '-t', @@ -125,7 +125,7 @@ Future runWebBenchmark(WebBenchmarkOptions benchmarkOptions) async { return Response.internalServerError(body: '$error'); } }).add(createBuildDirectoryHandler( - path.join(macrobenchmarksDirectory, 'build', 'web'), + path.join(macrobenchmarksDirectory, 'build', benchmarkOptions.useWasm ? 'web_wasm' : 'web'), )); server = await io.HttpServer.bind('localhost', benchmarkServerPort); diff --git a/dev/integration_tests/web_e2e_tests/web/index.html b/dev/integration_tests/web_e2e_tests/web/index.html index 70d8bac2919..9dcd43f6d12 100644 --- a/dev/integration_tests/web_e2e_tests/web/index.html +++ b/dev/integration_tests/web_e2e_tests/web/index.html @@ -5,17 +5,14 @@ found in the LICENSE file. --> Web Integration Tests - + - + diff --git a/packages/flutter_tools/lib/src/build_info.dart b/packages/flutter_tools/lib/src/build_info.dart index 59e24592620..6b107e10ab7 100644 --- a/packages/flutter_tools/lib/src/build_info.dart +++ b/packages/flutter_tools/lib/src/build_info.dart @@ -12,6 +12,7 @@ import 'base/os.dart'; import 'base/utils.dart'; import 'convert.dart'; import 'globals.dart' as globals; +import 'web/compile.dart'; /// Whether icon font subsetting is enabled by default. const bool kIconTreeShakerEnabledDefault = true; @@ -35,6 +36,7 @@ class BuildInfo { List? dartDefines, this.bundleSkSLPath, List? dartExperiments, + this.webRenderer = WebRendererMode.auto, required this.treeShakeIcons, this.performanceMeasurementFile, this.packagesPath = '.dart_tool/package_config.json', // TODO(zanderso): make this required and remove the default. @@ -128,6 +130,9 @@ class BuildInfo { /// A list of Dart experiments. final List dartExperiments; + /// When compiling to web, which web renderer mode we are using (html, canvaskit, auto) + final WebRendererMode webRenderer; + /// The name of a file where flutter assemble will output performance /// information in a JSON format. /// @@ -793,6 +798,10 @@ HostPlatform getCurrentHostPlatform() { return HostPlatform.linux_x64; } +FileSystemEntity getWebPlatformBinariesDirectory(Artifacts artifacts, WebRendererMode webRenderer) { + return artifacts.getHostArtifact(HostArtifact.webPlatformKernelFolder); +} + /// Returns the top-level build output directory. String getBuildDirectory([Config? config, FileSystem? fileSystem]) { // TODO(johnmccutchan): Stop calling this function as part of setting @@ -835,8 +844,8 @@ String getMacOSBuildDirectory() { } /// Returns the web build output directory. -String getWebBuildDirectory() { - return globals.fs.path.join(getBuildDirectory(), 'web'); +String getWebBuildDirectory([bool isWasm = false]) { + return globals.fs.path.join(getBuildDirectory(), isWasm ? 'web_wasm' : 'web'); } /// Returns the Linux build output directory. diff --git a/packages/flutter_tools/lib/src/build_system/build_system.dart b/packages/flutter_tools/lib/src/build_system/build_system.dart index 849f4f3ce06..2438202015e 100644 --- a/packages/flutter_tools/lib/src/build_system/build_system.dart +++ b/packages/flutter_tools/lib/src/build_system/build_system.dart @@ -136,15 +136,6 @@ abstract class Target { /// A list of zero or more depfiles, located directly under {BUILD_DIR}. List get depfiles => const []; - /// A string that differentiates different build variants from each other - /// with regards to build flags or settings on the target. This string should - /// represent each build variant as a different unique value. If this value - /// changes between builds, the target will be invalidated and rebuilt. - /// - /// By default, this returns null, which indicates there is only one build - /// variant, and the target won't invalidate or rebuild due to this property. - String? get buildKey => null; - /// Whether this target can be executed with the given [environment]. /// /// Returning `true` will cause [build] to be skipped. This is equivalent @@ -165,7 +156,6 @@ abstract class Target { [ for (final Target target in dependencies) target._toNode(environment), ], - buildKey, environment, inputsFiles.containsNewDepfile, ); @@ -191,11 +181,9 @@ abstract class Target { for (final File output in outputs) { outputPaths.add(output.path); } - final String? key = buildKey; final Map result = { 'inputs': inputPaths, 'outputs': outputPaths, - if (key != null) 'buildKey': key, }; if (!stamp.existsSync()) { stamp.createSync(); @@ -230,7 +218,6 @@ abstract class Target { /// This requires constants from the [Environment] to resolve the paths of /// inputs and the output stamp. Map toJson(Environment environment) { - final String? key = buildKey; return { 'name': name, 'dependencies': [ @@ -242,7 +229,6 @@ abstract class Target { 'outputs': [ for (final File file in resolveOutputs(environment).sources) file.path, ], - if (key != null) 'buildKey': key, 'stamp': _findStampFile(environment).absolute.path, }; } @@ -994,85 +980,49 @@ void verifyOutputDirectories(List outputs, Environment environment, Target /// A node in the build graph. class Node { - factory Node( - Target target, - List inputs, - List outputs, - List dependencies, - String? buildKey, + Node( + this.target, + this.inputs, + this.outputs, + this.dependencies, Environment environment, - bool missingDepfile, + this.missingDepfile, ) { final File stamp = target._findStampFile(environment); - Map? stampValues; // If the stamp file doesn't exist, we haven't run this step before and // all inputs were added. - if (stamp.existsSync()) { - final String content = stamp.readAsStringSync(); - if (content.isEmpty) { - stamp.deleteSync(); - } else { - try { - stampValues = castStringKeyedMap(json.decode(content)); - } on FormatException { - // The json is malformed in some way. - } - } - } - if (stampValues != null) { - final String? previousBuildKey = stampValues['buildKey'] as String?; - final Object? stampInputs = stampValues['inputs']; - final Object? stampOutputs = stampValues['outputs']; - if (stampInputs is List && stampOutputs is List) { - final Set previousInputs = stampInputs.whereType().toSet(); - final Set previousOutputs = stampOutputs.whereType().toSet(); - return Node.withStamp( - target, - inputs, - previousInputs, - outputs, - previousOutputs, - dependencies, - buildKey, - previousBuildKey, - missingDepfile, - ); - } - } - return Node.withNoStamp( - target, - inputs, - outputs, - dependencies, - buildKey, - missingDepfile, - ); - } - - Node.withNoStamp( - this.target, - this.inputs, - this.outputs, - this.dependencies, - this.buildKey, - this.missingDepfile, - ) : previousInputs = {}, - previousOutputs = {}, - previousBuildKey = null, + if (!stamp.existsSync()) { + // No stamp file, not safe to skip. _dirty = true; - - Node.withStamp( - this.target, - this.inputs, - this.previousInputs, - this.outputs, - this.previousOutputs, - this.dependencies, - this.buildKey, - this.previousBuildKey, - this.missingDepfile, - ) : _dirty = false; + return; + } + final String content = stamp.readAsStringSync(); + // Something went wrong writing the stamp file. + if (content.isEmpty) { + stamp.deleteSync(); + // Malformed stamp file, not safe to skip. + _dirty = true; + return; + } + Map? values; + try { + values = castStringKeyedMap(json.decode(content)); + } on FormatException { + // The json is malformed in some way. + _dirty = true; + return; + } + final Object? inputs = values?['inputs']; + final Object? outputs = values?['outputs']; + if (inputs is List && outputs is List) { + inputs.cast().whereType().forEach(previousInputs.add); + outputs.cast().whereType().forEach(previousOutputs.add); + } else { + // The json is malformed in some way. + _dirty = true; + } + } /// The resolved input files. /// @@ -1084,11 +1034,6 @@ class Node { /// These files may not yet exist if the target hasn't run yet. final List outputs; - /// The current build key of the target - /// - /// See `buildKey` in the `Target` class for more information. - final String? buildKey; - /// Whether this node is missing a depfile. /// /// This requires an additional pass of source resolution after the target @@ -1102,15 +1047,10 @@ class Node { final List dependencies; /// Output file paths from the previous invocation of this build node. - final Set previousOutputs; + final Set previousOutputs = {}; /// Input file paths from the previous invocation of this build node. - final Set previousInputs; - - /// The buildKey from the previous invocation of this build node. - /// - /// See `buildKey` in the `Target` class for more information. - final String? previousBuildKey; + final Set previousInputs = {}; /// One or more reasons why a task was invalidated. /// @@ -1134,10 +1074,6 @@ class Node { FileSystem fileSystem, Logger logger, ) { - if (buildKey != previousBuildKey) { - _invalidate(InvalidatedReasonKind.buildKeyChanged); - _dirty = true; - } final Set currentOutputPaths = { for (final File file in outputs) file.path, }; @@ -1237,8 +1173,7 @@ class InvalidatedReason { InvalidatedReasonKind.inputChanged => 'The following inputs have updated contents: ${data.join(',')}', InvalidatedReasonKind.outputChanged => 'The following outputs have updated contents: ${data.join(',')}', InvalidatedReasonKind.outputMissing => 'The following outputs were missing: ${data.join(',')}', - InvalidatedReasonKind.outputSetChanged => 'The following outputs were removed from the output set: ${data.join(',')}', - InvalidatedReasonKind.buildKeyChanged => 'The target build key changed.', + InvalidatedReasonKind.outputSetChanged => 'The following outputs were removed from the output set: ${data.join(',')}' }; } } @@ -1260,7 +1195,4 @@ enum InvalidatedReasonKind { /// The set of expected output files changed. outputSetChanged, - - /// The build key changed - buildKeyChanged, } diff --git a/packages/flutter_tools/lib/src/build_system/build_targets.dart b/packages/flutter_tools/lib/src/build_system/build_targets.dart index 8a71c0bc233..755e1482c63 100644 --- a/packages/flutter_tools/lib/src/build_system/build_targets.dart +++ b/packages/flutter_tools/lib/src/build_system/build_targets.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import '../base/file_system.dart'; -import '../web/compiler_config.dart'; +import '../web/compile.dart'; import './build_system.dart'; /// Commonly used build [Target]s. @@ -14,7 +14,11 @@ abstract class BuildTargets { Target get releaseCopyFlutterBundle; Target get generateLocalizationsTarget; Target get dartPluginRegistrantTarget; - Target webServiceWorker(FileSystem fileSystem, List compileConfigs); + Target webServiceWorker( + FileSystem fileSystem, { + required WebRendererMode webRenderer, + required bool isWasm + }); } /// BuildTargets that return NoOpTarget for every action. @@ -34,7 +38,11 @@ class NoOpBuildTargets extends BuildTargets { Target get dartPluginRegistrantTarget => const _NoOpTarget(); @override - Target webServiceWorker(FileSystem fileSystem, List compileConfigs) => const _NoOpTarget(); + Target webServiceWorker( + FileSystem fileSystem, { + required WebRendererMode webRenderer, + required bool isWasm, + }) => const _NoOpTarget(); } /// A [Target] that does nothing. diff --git a/packages/flutter_tools/lib/src/build_system/targets/web.dart b/packages/flutter_tools/lib/src/build_system/targets/web.dart index 86e65c2fe59..4ffe6150b12 100644 --- a/packages/flutter_tools/lib/src/build_system/targets/web.dart +++ b/packages/flutter_tools/lib/src/build_system/targets/web.dart @@ -5,7 +5,6 @@ import 'dart:math'; import 'package:crypto/crypto.dart'; -import 'package:meta/meta.dart'; import 'package:package_config/package_config.dart'; import '../../artifacts.dart'; @@ -23,23 +22,13 @@ import '../../project.dart'; import '../../web/compile.dart'; import '../../web/file_generators/flutter_service_worker_js.dart'; import '../../web/file_generators/main_dart.dart' as main_dart; +import '../../web/file_generators/wasm_bootstrap.dart' as wasm_bootstrap; import '../build_system.dart'; import '../depfile.dart'; import '../exceptions.dart'; import 'assets.dart'; import 'localizations.dart'; -@visibleForTesting -List updateDartDefines(List dartDefines, WebRendererMode webRenderer) { - final Set dartDefinesSet = dartDefines.toSet(); - if (!dartDefines.any((String d) => d.startsWith('FLUTTER_WEB_AUTO_DETECT=')) - && dartDefines.any((String d) => d.startsWith('FLUTTER_WEB_USE_SKIA='))) { - dartDefinesSet.removeWhere((String d) => d.startsWith('FLUTTER_WEB_USE_SKIA=')); - } - dartDefinesSet.addAll(webRenderer.dartDefines); - return dartDefinesSet.toList(); -} - /// Generates an entry point for a web target. // Keep this in sync with build_runner/resident_web_runner.dart class WebEntrypointTarget extends Target { @@ -106,15 +95,11 @@ class WebEntrypointTarget extends Target { /// Compiles a web entry point with dart2js. abstract class Dart2WebTarget extends Target { - const Dart2WebTarget(); + const Dart2WebTarget(this.webRenderer); + final WebRendererMode webRenderer; Source get compilerSnapshot; - WebCompilerConfig get compilerConfig; - - Map get buildConfig; - List get buildFiles; - @override List get dependencies => const [ WebEntrypointTarget(), @@ -131,19 +116,11 @@ abstract class Dart2WebTarget extends Target { ]; @override - List get outputs => buildFiles.map( - (String file) => Source.pattern('{BUILD_DIR}/$file') - ).toList(); - - @override - String get buildKey => compilerConfig.buildKey; + List get outputs => const []; } class Dart2JSTarget extends Dart2WebTarget { - Dart2JSTarget(this.compilerConfig); - - @override - final JsCompilerConfig compilerConfig; + Dart2JSTarget(super.webRenderer); @override String get name => 'dart2js'; @@ -163,12 +140,9 @@ class Dart2JSTarget extends Dart2WebTarget { throw MissingDefineException(kBuildMode, name); } final BuildMode buildMode = BuildMode.fromCliName(buildModeEnvironment); + final JsCompilerConfig compilerConfig = JsCompilerConfig.fromBuildSystemEnvironment(environment.defines); final Artifacts artifacts = environment.artifacts; - final String platformBinariesPath = artifacts.getHostArtifact(HostArtifact.webPlatformKernelFolder).path; - final List dartDefines = updateDartDefines( - decodeDartDefines(environment.defines, kDartDefines), - compilerConfig.renderer, - ); + final String platformBinariesPath = getWebPlatformBinariesDirectory(artifacts, webRenderer).path; final List sharedCommandOptions = [ artifacts.getArtifactPath(Artifact.engineDartBinary, platform: TargetPlatform.web_javascript), '--disable-dart-dev', @@ -180,7 +154,7 @@ class Dart2JSTarget extends Dart2WebTarget { '-Ddart.vm.profile=true' else '-Ddart.vm.product=true', - for (final String dartDefine in dartDefines) + for (final String dartDefine in decodeDartDefines(environment.defines, kDartDefines)) '-D$dartDefine', ]; @@ -234,25 +208,10 @@ class Dart2JSTarget extends Dart2WebTarget { environment.buildDir.childFile('dart2js.d'), ); } - - @override - Map get buildConfig => { - 'compileTarget': 'dart2js', - 'renderer': compilerConfig.renderer.name, - 'mainJsPath': 'main.dart.js', - }; - - @override - List get buildFiles => [ - 'main.dart.js', - ]; } class Dart2WasmTarget extends Dart2WebTarget { - Dart2WasmTarget(this.compilerConfig); - - @override - final WasmCompilerConfig compilerConfig; + Dart2WasmTarget(super.webRenderer); @override Future build(Environment environment) async { @@ -260,6 +219,7 @@ class Dart2WasmTarget extends Dart2WebTarget { if (buildModeEnvironment == null) { throw MissingDefineException(kBuildMode, name); } + final WasmCompilerConfig compilerConfig = WasmCompilerConfig.fromBuildSystemEnvironment(environment.defines); final BuildMode buildMode = BuildMode.fromCliName(buildModeEnvironment); final Artifacts artifacts = environment.artifacts; final File outputWasmFile = environment.buildDir.childFile( @@ -267,12 +227,8 @@ class Dart2WasmTarget extends Dart2WebTarget { ); final File depFile = environment.buildDir.childFile('dart2wasm.d'); final String dartSdkPath = artifacts.getArtifactPath(Artifact.engineDartSdkPath, platform: TargetPlatform.web_javascript); - final String platformBinariesPath = artifacts.getHostArtifact(HostArtifact.webPlatformKernelFolder).path; + final String platformBinariesPath = getWebPlatformBinariesDirectory(artifacts, webRenderer).path; final String platformFilePath = environment.fileSystem.path.join(platformBinariesPath, 'dart2wasm_platform.dill'); - final List dartDefines = updateDartDefines( - decodeDartDefines(environment.defines, kDartDefines), - compilerConfig.renderer, - ); final List compilationArgs = [ artifacts.getArtifactPath(Artifact.engineDartAotRuntime, platform: TargetPlatform.web_javascript), @@ -286,10 +242,10 @@ class Dart2WasmTarget extends Dart2WebTarget { else '-Ddart.vm.product=true', ...decodeCommaSeparated(environment.defines, kExtraFrontEndOptions), - for (final String dartDefine in dartDefines) + for (final String dartDefine in decodeDartDefines(environment.defines, kDartDefines)) '-D$dartDefine', ...compilerConfig.toCommandOptions(), - if (compilerConfig.renderer == WebRendererMode.skwasm) + if (webRenderer == WebRendererMode.skwasm) ...[ '--import-shared-memory', '--shared-memory-max-pages=32768', @@ -354,75 +310,74 @@ class Dart2WasmTarget extends Dart2WebTarget { ]; @override - Map get buildConfig => { - 'compileTarget': 'dart2wasm', - 'renderer': compilerConfig.renderer.name, - 'mainWasmPath': 'main.dart.wasm', - 'jsSupportRuntimePath': 'main.dart.mjs', - }; - - @override - List get buildFiles => [ - 'main.dart.wasm', - 'main.dart.mjs', + List get outputs => const [ + Source.pattern('{OUTPUT_DIR}/main.dart.wasm'), + Source.pattern('{OUTPUT_DIR}/main.dart.mjs'), ]; } /// Unpacks the dart2js or dart2wasm compilation and resources to a given /// output directory. class WebReleaseBundle extends Target { - WebReleaseBundle(List configs) : this._withTargets( - configs.map((WebCompilerConfig config) => - switch (config) { - WasmCompilerConfig() => Dart2WasmTarget(config), - JsCompilerConfig() => Dart2JSTarget(config), - } - ).toList() - ); + const WebReleaseBundle(this.webRenderer, {required this.isWasm}); - const WebReleaseBundle._withTargets(this.compileTargets); + final WebRendererMode webRenderer; + final bool isWasm; - final List compileTargets; - - List get buildFiles => compileTargets.fold( - const Iterable.empty(), - (Iterable current, Dart2WebTarget target) => current.followedBy(target.buildFiles) - ).toList(); + String get outputFileNameNoSuffix => 'main.dart'; + String get outputFileName => '$outputFileNameNoSuffix${isWasm ? '.wasm' : '.js'}'; + String get wasmJSRuntimeFileName => '$outputFileNameNoSuffix.mjs'; @override String get name => 'web_release_bundle'; @override - List get dependencies => compileTargets; + List get dependencies => [ + if (isWasm) Dart2WasmTarget(webRenderer) else Dart2JSTarget(webRenderer), + ]; @override List get inputs => [ + Source.pattern('{BUILD_DIR}/$outputFileName'), const Source.pattern('{PROJECT_DIR}/pubspec.yaml'), - ...buildFiles.map((String file) => Source.pattern('{BUILD_DIR}/$file')) + if (isWasm) Source.pattern('{BUILD_DIR}/$wasmJSRuntimeFileName'), ]; @override List get outputs => [ - ...buildFiles.map((String file) => Source.pattern('{OUTPUT_DIR}/$file')) + Source.pattern('{OUTPUT_DIR}/$outputFileName'), + if (isWasm) Source.pattern('{OUTPUT_DIR}/$wasmJSRuntimeFileName'), ]; @override List get depfiles => const [ + 'dart2js.d', 'flutter_assets.d', 'web_resources.d', ]; + bool shouldCopy(String name) => + // Do not copy the deps file. + (name.contains(outputFileName) && !name.endsWith('.deps')) || + (isWasm && name == wasmJSRuntimeFileName); + @override Future build(Environment environment) async { for (final File outputFile in environment.buildDir.listSync(recursive: true).whereType()) { final String basename = environment.fileSystem.path.basename(outputFile.path); - if (buildFiles.contains(basename)) { + if (shouldCopy(basename)) { outputFile.copySync( environment.outputDir.childFile(environment.fileSystem.path.basename(outputFile.path)).path ); } } + if (isWasm) { + // TODO(jacksongardner): Enable icon tree shaking once dart2wasm can do a two-phase compile. + // https://github.com/flutter/flutter/issues/117248 + environment.defines[kIconTreeShakerFlag] = 'false'; + } + createVersionFile(environment, environment.defines); final Directory outputDirectory = environment.outputDir.childDirectory('assets'); outputDirectory.createSync(recursive: true); @@ -458,19 +413,10 @@ class WebReleaseBundle extends Target { // because it would need to be the hash for the entire bundle and not just the resource // in question. if (environment.fileSystem.path.basename(inputFile.path) == 'index.html') { - final List> buildDescriptions = compileTargets.map( - (Dart2WebTarget target) => target.buildConfig - ).toList(); - final Map buildConfig = { - 'engineRevision': globals.flutterVersion.engineRevision, - 'builds': buildDescriptions, - }; - final String buildConfigString = '_flutter.buildConfig = ${jsonEncode(buildConfig)};'; final IndexHtml indexHtml = IndexHtml(inputFile.readAsStringSync()); indexHtml.applySubstitutions( baseHref: environment.defines[kBaseHref] ?? '/', serviceWorkerVersion: Random().nextInt(4294967296).toString(), - buildConfig: buildConfigString, ); outputFile.writeAsStringSync(indexHtml.content); continue; @@ -510,9 +456,11 @@ class WebReleaseBundle extends Target { /// These assets can be cached until a new version of the flutter web sdk is /// downloaded. class WebBuiltInAssets extends Target { - const WebBuiltInAssets(this.fileSystem); + const WebBuiltInAssets(this.fileSystem, this.webRenderer, {required this.isWasm}); final FileSystem fileSystem; + final WebRendererMode webRenderer; + final bool isWasm; @override String get name => 'web_static_assets'; @@ -543,6 +491,7 @@ class WebBuiltInAssets extends Target { @override List get outputs => [ + if (isWasm) const Source.pattern('{BUILD_DIR}/main.dart.js'), const Source.pattern('{BUILD_DIR}/flutter.js'), for (final File file in _canvasKitFiles) Source.pattern('{BUILD_DIR}/canvaskit/${_filePathRelativeToCanvasKitDirectory(file)}'), @@ -556,6 +505,13 @@ class WebBuiltInAssets extends Target { file.copySync(targetPath); } + if (isWasm) { + final File bootstrapFile = environment.outputDir.childFile('main.dart.js'); + bootstrapFile.writeAsStringSync( + wasm_bootstrap.generateWasmBootstrapFile(webRenderer == WebRendererMode.skwasm) + ); + } + // Write the flutter.js file final String flutterJsOut = fileSystem.path.join(environment.outputDir.path, 'flutter.js'); final File flutterJsFile = fileSystem.file(fileSystem.path.join( @@ -568,18 +524,20 @@ class WebBuiltInAssets extends Target { /// Generate a service worker for a web target. class WebServiceWorker extends Target { - const WebServiceWorker(this.fileSystem, this.compileConfigs); + const WebServiceWorker(this.fileSystem, this.webRenderer, {required this.isWasm}); final FileSystem fileSystem; - final List compileConfigs; + final WebRendererMode webRenderer; + final bool isWasm; @override String get name => 'web_service_worker'; @override List get dependencies => [ - WebReleaseBundle(compileConfigs), - WebBuiltInAssets(fileSystem), + if (isWasm) Dart2WasmTarget(webRenderer) else Dart2JSTarget(webRenderer), + WebReleaseBundle(webRenderer, isWasm: isWasm), + WebBuiltInAssets(fileSystem, webRenderer, isWasm: isWasm), ]; @override @@ -634,10 +592,6 @@ class WebServiceWorker extends Target { urlToHash, [ 'main.dart.js', - if (compileConfigs.any((WebCompilerConfig config) => config is WasmCompilerConfig)) ...[ - 'main.dart.wasm', - 'main.dart.mjs', - ], 'index.html', if (urlToHash.containsKey('assets/AssetManifest.bin.json')) 'assets/AssetManifest.bin.json', diff --git a/packages/flutter_tools/lib/src/commands/build_web.dart b/packages/flutter_tools/lib/src/commands/build_web.dart index 7be2209167c..52e2410ffac 100644 --- a/packages/flutter_tools/lib/src/commands/build_web.dart +++ b/packages/flutter_tools/lib/src/commands/build_web.dart @@ -138,50 +138,24 @@ class BuildWebCommand extends BuildSubCommand { throwToolExit('"build web" is not currently supported. To enable, run "flutter config --enable-web".'); } - final List compilerConfigs; + final WebCompilerConfig compilerConfig; if (boolArg('wasm')) { if (!featureFlags.isFlutterWebWasmEnabled) { throwToolExit('Compiling to WebAssembly (wasm) is only available on the master channel.'); } - if (stringArg(FlutterOptions.kWebRendererFlag) != argParser.defaultFor(FlutterOptions.kWebRendererFlag)) { - throwToolExit('"--${FlutterOptions.kWebRendererFlag}" cannot be combined with "--${FlutterOptions.kWebWasmFlag}"'); - } - globals.logger.printBox( - title: 'Experimental feature', - ''' - WebAssembly compilation is experimental. - $kWasmMoreInfo''', + compilerConfig = WasmCompilerConfig( + omitTypeChecks: boolArg('omit-type-checks'), + wasmOpt: WasmOptLevel.values.byName(stringArg('wasm-opt')!), ); - - compilerConfigs = [ - WasmCompilerConfig( - omitTypeChecks: boolArg('omit-type-checks'), - wasmOpt: WasmOptLevel.values.byName(stringArg('wasm-opt')!), - renderer: WebRendererMode.skwasm, - ), - JsCompilerConfig( - csp: boolArg('csp'), - optimizationLevel: stringArg('dart2js-optimization') ?? JsCompilerConfig.kDart2jsDefaultOptimizationLevel, - dumpInfo: boolArg('dump-info'), - nativeNullAssertions: boolArg('native-null-assertions'), - noFrequencyBasedMinification: boolArg('no-frequency-based-minification'), - sourceMaps: boolArg('source-maps'), - renderer: WebRendererMode.canvaskit, - )]; } else { - WebRendererMode webRenderer = WebRendererMode.auto; - if (argParser.options.containsKey(FlutterOptions.kWebRendererFlag)) { - webRenderer = WebRendererMode.values.byName(stringArg(FlutterOptions.kWebRendererFlag)!); - } - compilerConfigs = [JsCompilerConfig( + compilerConfig = JsCompilerConfig( csp: boolArg('csp'), optimizationLevel: stringArg('dart2js-optimization') ?? JsCompilerConfig.kDart2jsDefaultOptimizationLevel, dumpInfo: boolArg('dump-info'), nativeNullAssertions: boolArg('native-null-assertions'), noFrequencyBasedMinification: boolArg('no-frequency-based-minification'), sourceMaps: boolArg('source-maps'), - renderer: webRenderer, - )]; + ); } final FlutterProject flutterProject = FlutterProject.current(); @@ -231,7 +205,7 @@ class BuildWebCommand extends BuildSubCommand { target, buildInfo, ServiceWorkerStrategy.fromCliName(stringArg('pwa-strategy')), - compilerConfigs: compilerConfigs, + compilerConfig: compilerConfig, baseHref: baseHref, outputDirectoryPath: outputDirectoryPath, ); diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart index ceccfbd939d..993a685abd6 100644 --- a/packages/flutter_tools/lib/src/commands/run.dart +++ b/packages/flutter_tools/lib/src/commands/run.dart @@ -29,7 +29,6 @@ import '../runner/flutter_command.dart'; import '../runner/flutter_command_runner.dart'; import '../tracing.dart'; import '../vmservice.dart'; -import '../web/compile.dart'; import '../web/web_runner.dart'; import 'daemon.dart'; @@ -242,10 +241,6 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment final Map webHeaders = featureFlags.isWebEnabled ? extractWebHeaders() : const {}; - final String? webRendererString = stringArg('web-renderer'); - final WebRendererMode webRenderer = (webRendererString != null) - ? WebRendererMode.values.byName(webRendererString) - : WebRendererMode.auto; if (buildInfo.mode.isRelease) { return DebuggingOptions.disabled( @@ -263,7 +258,6 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment webBrowserDebugPort: webBrowserDebugPort, webBrowserFlags: webBrowserFlags, webHeaders: webHeaders, - webRenderer: webRenderer, enableImpeller: enableImpeller, enableVulkanValidation: enableVulkanValidation, uninstallFirst: uninstallFirst, @@ -313,7 +307,6 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment webEnableExpressionEvaluation: featureFlags.isWebEnabled && boolArg('web-enable-expression-evaluation'), webLaunchUrl: featureFlags.isWebEnabled ? stringArg('web-launch-url') : null, webHeaders: webHeaders, - webRenderer: webRenderer, vmserviceOutFile: stringArg('vmservice-out-file'), fastStart: argParser.options.containsKey('fast-start') && boolArg('fast-start') diff --git a/packages/flutter_tools/lib/src/commands/test.dart b/packages/flutter_tools/lib/src/commands/test.dart index 9be50579991..1190181b479 100644 --- a/packages/flutter_tools/lib/src/commands/test.dart +++ b/packages/flutter_tools/lib/src/commands/test.dart @@ -22,7 +22,6 @@ import '../test/runner.dart'; import '../test/test_time_recorder.dart'; import '../test/test_wrapper.dart'; import '../test/watcher.dart'; -import '../web/compile.dart'; /// The name of the directory where Integration Tests are placed. /// @@ -358,10 +357,6 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts { ); } - final String? webRendererString = stringArg('web-renderer'); - final WebRendererMode webRenderer = (webRendererString != null) - ? WebRendererMode.values.byName(webRendererString) - : WebRendererMode.auto; final DebuggingOptions debuggingOptions = DebuggingOptions.enabled( buildInfo, startPaused: startPaused, @@ -374,7 +369,6 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts { usingCISystem: usingCISystem, enableImpeller: ImpellerStatus.fromBool(argResults!['enable-impeller'] as bool?), debugLogsDirectoryPath: debugLogsDirectoryPath, - webRenderer: webRenderer, ); String? testAssetDirectory; diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart index 1f0cc0b2414..69938a9b784 100644 --- a/packages/flutter_tools/lib/src/device.dart +++ b/packages/flutter_tools/lib/src/device.dart @@ -18,7 +18,6 @@ import 'devfs.dart'; import 'device_port_forwarder.dart'; import 'project.dart'; import 'vmservice.dart'; -import 'web/compile.dart'; DeviceManager? get deviceManager => context.get(); @@ -953,7 +952,6 @@ class DebuggingOptions { this.webEnableExpressionEvaluation = false, this.webHeaders = const {}, this.webLaunchUrl, - this.webRenderer = WebRendererMode.auto, this.vmserviceOutFile, this.fastStart = false, this.nullAssertions = false, @@ -983,7 +981,6 @@ class DebuggingOptions { this.webBrowserFlags = const [], this.webLaunchUrl, this.webHeaders = const {}, - this.webRenderer = WebRendererMode.auto, this.cacheSkSL = false, this.traceAllowlist, this.enableImpeller = ImpellerStatus.platformDefault, @@ -1063,7 +1060,6 @@ class DebuggingOptions { required this.webEnableExpressionEvaluation, required this.webHeaders, required this.webLaunchUrl, - required this.webRenderer, required this.vmserviceOutFile, required this.fastStart, required this.nullAssertions, @@ -1148,9 +1144,6 @@ class DebuggingOptions { /// Allow developers to add custom headers to web server final Map webHeaders; - /// Which web renderer to use for the debugging session - final WebRendererMode webRenderer; - /// A file where the VM Service URL should be written after the application is started. final String? vmserviceOutFile; final bool fastStart; @@ -1259,7 +1252,6 @@ class DebuggingOptions { 'webEnableExpressionEvaluation': webEnableExpressionEvaluation, 'webLaunchUrl': webLaunchUrl, 'webHeaders': webHeaders, - 'webRenderer': webRenderer.name, 'vmserviceOutFile': vmserviceOutFile, 'fastStart': fastStart, 'nullAssertions': nullAssertions, @@ -1315,7 +1307,6 @@ class DebuggingOptions { webEnableExpressionEvaluation: json['webEnableExpressionEvaluation']! as bool, webHeaders: (json['webHeaders']! as Map).cast(), webLaunchUrl: json['webLaunchUrl'] as String?, - webRenderer: WebRendererMode.values.byName(json['webRenderer']! as String), vmserviceOutFile: json['vmserviceOutFile'] as String?, fastStart: json['fastStart']! as bool, nullAssertions: json['nullAssertions']! as bool, diff --git a/packages/flutter_tools/lib/src/drive/web_driver_service.dart b/packages/flutter_tools/lib/src/drive/web_driver_service.dart index fa10cfb1cf1..8f6241a5de5 100644 --- a/packages/flutter_tools/lib/src/drive/web_driver_service.dart +++ b/packages/flutter_tools/lib/src/drive/web_driver_service.dart @@ -78,14 +78,12 @@ class WebDriverService extends DriverService { buildInfo, port: debuggingOptions.port, hostname: debuggingOptions.hostname, - webRenderer: debuggingOptions.webRenderer, ) : DebuggingOptions.enabled( buildInfo, port: debuggingOptions.port, hostname: debuggingOptions.hostname, disablePortPublication: debuggingOptions.disablePortPublication, - webRenderer: debuggingOptions.webRenderer, ), stayResident: true, flutterProject: FlutterProject.current(), diff --git a/packages/flutter_tools/lib/src/html_utils.dart b/packages/flutter_tools/lib/src/html_utils.dart index 2477a90b2d4..ad394aaa909 100644 --- a/packages/flutter_tools/lib/src/html_utils.dart +++ b/packages/flutter_tools/lib/src/html_utils.dart @@ -62,7 +62,6 @@ class IndexHtml { void applySubstitutions({ required String baseHref, required String? serviceWorkerVersion, - String? buildConfig, }) { if (_content.contains(kBaseHrefPlaceholder)) { _content = _content.replaceAll(kBaseHrefPlaceholder, baseHref); @@ -82,12 +81,6 @@ class IndexHtml { "navigator.serviceWorker.register('flutter_service_worker.js?v=$serviceWorkerVersion')", ); } - if (buildConfig != null) { - _content = _content.replaceFirst( - '{{flutter_build_config}}', - buildConfig, - ); - } } } diff --git a/packages/flutter_tools/lib/src/isolated/build_targets.dart b/packages/flutter_tools/lib/src/isolated/build_targets.dart index e721495a289..5a7a70fabcc 100644 --- a/packages/flutter_tools/lib/src/isolated/build_targets.dart +++ b/packages/flutter_tools/lib/src/isolated/build_targets.dart @@ -9,7 +9,7 @@ import '../build_system/targets/common.dart'; import '../build_system/targets/dart_plugin_registrant.dart'; import '../build_system/targets/localizations.dart'; import '../build_system/targets/web.dart'; -import '../web/compiler_config.dart'; +import '../web/compile.dart'; class BuildTargetsImpl extends BuildTargets { const BuildTargetsImpl(); @@ -27,6 +27,9 @@ class BuildTargetsImpl extends BuildTargets { Target get dartPluginRegistrantTarget => const DartPluginRegistrantTarget(); @override - Target webServiceWorker(FileSystem fileSystem, List compileConfigs) => - WebServiceWorker(fileSystem, compileConfigs); + Target webServiceWorker( + FileSystem fileSystem, { + required WebRendererMode webRenderer, + required bool isWasm, + }) => WebServiceWorker(fileSystem, webRenderer, isWasm: isWasm); } diff --git a/packages/flutter_tools/lib/src/isolated/devfs_web.dart b/packages/flutter_tools/lib/src/isolated/devfs_web.dart index 61714715fb2..813006a9a2e 100644 --- a/packages/flutter_tools/lib/src/isolated/devfs_web.dart +++ b/packages/flutter_tools/lib/src/isolated/devfs_web.dart @@ -117,9 +117,8 @@ class WebAssetServer implements AssetReader { this.internetAddress, this._modules, this._digests, - this._nullSafetyMode, { - required this.webRenderer, - }) : basePath = _getIndexHtml().getBaseHref(); + this._nullSafetyMode, + ) : basePath = _getIndexHtml().getBaseHref(); // Fallback to "application/octet-stream" on null which // makes no claims as to the structure of the data. @@ -178,7 +177,6 @@ class WebAssetServer implements AssetReader { ExpressionCompiler? expressionCompiler, Map extraHeaders, NullSafetyMode nullSafetyMode, { - required WebRendererMode webRenderer, bool testMode = false, DwdsLauncher dwdsLauncher = Dwds.start, }) async { @@ -227,7 +225,6 @@ class WebAssetServer implements AssetReader { modules, digests, nullSafetyMode, - webRenderer: webRenderer, ); if (testMode) { return server; @@ -507,29 +504,16 @@ class WebAssetServer implements AssetReader { } /// Determines what rendering backed to use. - final WebRendererMode webRenderer; + WebRendererMode webRenderer = WebRendererMode.html; shelf.Response _serveIndex() { final IndexHtml indexHtml = _getIndexHtml(); - final Map buildConfig = { - 'engineRevision': globals.flutterVersion.engineRevision, - 'builds': [ - { - 'compileTarget': 'dartdevc', - 'renderer': webRenderer.name, - 'mainJsPath': 'main.dart.js', - }, - ], - }; - final String buildConfigString = '_flutter.buildConfig = ${jsonEncode(buildConfig)};'; - indexHtml.applySubstitutions( // Currently, we don't support --base-href for the "run" command. baseHref: '/', serviceWorkerVersion: null, - buildConfig: buildConfigString, ); final Map headers = { @@ -679,7 +663,6 @@ class WebDevFS implements DevFS { required this.nullAssertions, required this.nativeNullAssertions, required this.nullSafetyMode, - required this.webRenderer, this.testMode = false, }) : _port = port; @@ -703,7 +686,6 @@ class WebDevFS implements DevFS { final NullSafetyMode nullSafetyMode; final String? tlsCertPath; final String? tlsCertKeyPath; - final WebRendererMode webRenderer; late WebAssetServer webAssetServer; @@ -803,11 +785,15 @@ class WebDevFS implements DevFS { expressionCompiler, extraHeaders, nullSafetyMode, - webRenderer: webRenderer, testMode: testMode, ); final int selectedPort = webAssetServer.selectedPort; + if (buildInfo.dartDefines.contains('FLUTTER_WEB_AUTO_DETECT=true')) { + webAssetServer.webRenderer = WebRendererMode.auto; + } else if (buildInfo.dartDefines.contains('FLUTTER_WEB_USE_SKIA=true')) { + webAssetServer.webRenderer = WebRendererMode.canvaskit; + } String url = '$hostname:$selectedPort'; if (hostname == 'any') { url ='localhost:$selectedPort'; diff --git a/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart b/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart index 7a62b7815e0..45a7b184117 100644 --- a/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart +++ b/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart @@ -309,7 +309,6 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive). nullAssertions: debuggingOptions.nullAssertions, nullSafetyMode: debuggingOptions.buildInfo.nullSafetyMode, nativeNullAssertions: debuggingOptions.nativeNullAssertions, - webRenderer: debuggingOptions.webRenderer, ); Uri url = await device!.devFS!.create(); if (debuggingOptions.tlsCertKeyPath != null && debuggingOptions.tlsCertPath != null) { @@ -340,12 +339,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive). target, debuggingOptions.buildInfo, ServiceWorkerStrategy.none, - compilerConfigs: [ - JsCompilerConfig.run( - nativeNullAssertions: debuggingOptions.nativeNullAssertions, - renderer: debuggingOptions.webRenderer, - ) - ] + compilerConfig: JsCompilerConfig.run(nativeNullAssertions: debuggingOptions.nativeNullAssertions) ); } await device!.device!.startApp( @@ -424,12 +418,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive). target, debuggingOptions.buildInfo, ServiceWorkerStrategy.none, - compilerConfigs: [ - JsCompilerConfig.run( - nativeNullAssertions: debuggingOptions.nativeNullAssertions, - renderer: debuggingOptions.webRenderer, - ) - ], + compilerConfig: JsCompilerConfig.run(nativeNullAssertions: debuggingOptions.nativeNullAssertions), ); } on ToolExit { return OperationResult(1, 'Failed to recompile application.'); diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart index a0f6713eb20..c918031f876 100644 --- a/packages/flutter_tools/lib/src/resident_runner.dart +++ b/packages/flutter_tools/lib/src/resident_runner.dart @@ -135,7 +135,7 @@ class FlutterDevice { } final String platformDillPath = globals.fs.path.join( - globals.artifacts!.getHostArtifact(HostArtifact.webPlatformKernelFolder).path, + getWebPlatformBinariesDirectory(globals.artifacts!, buildInfo.webRenderer).path, platformDillName, ); diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart index 706737695eb..715fe1049ae 100644 --- a/packages/flutter_tools/lib/src/runner/flutter_command.dart +++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart @@ -1263,7 +1263,13 @@ abstract class FlutterCommand extends Command { : null; final Map defineConfigJsonMap = extractDartDefineConfigJsonMap(); - final List dartDefines = extractDartDefines(defineConfigJsonMap: defineConfigJsonMap); + List dartDefines = extractDartDefines(defineConfigJsonMap: defineConfigJsonMap); + + WebRendererMode webRenderer = WebRendererMode.auto; + if (argParser.options.containsKey(FlutterOptions.kWebRendererFlag)) { + webRenderer = WebRendererMode.values.byName(stringArg(FlutterOptions.kWebRendererFlag)!); + dartDefines = updateDartDefines(dartDefines, webRenderer); + } if (argParser.options.containsKey(FlutterOptions.kWebResourcesCdnFlag)) { final bool hasLocalWebSdk = argParser.options.containsKey('local-web-sdk') && stringArg('local-web-sdk') != null; @@ -1311,6 +1317,7 @@ abstract class FlutterCommand extends Command { dartDefines: dartDefines, bundleSkSLPath: bundleSkSLPath, dartExperiments: experiments, + webRenderer: webRenderer, performanceMeasurementFile: performanceMeasurementFile, packagesPath: packagesPath ?? globals.fs.path.absolute('.dart_tool', 'package_config.json'), nullSafetyMode: nullSafetyMode, @@ -1548,6 +1555,19 @@ abstract class FlutterCommand extends Command { return jsonEncode(propertyMap); } + /// Updates dart-defines based on [webRenderer]. + @visibleForTesting + static List updateDartDefines(List dartDefines, WebRendererMode webRenderer) { + final Set dartDefinesSet = dartDefines.toSet(); + if (!dartDefines.any((String d) => d.startsWith('FLUTTER_WEB_AUTO_DETECT=')) + && dartDefines.any((String d) => d.startsWith('FLUTTER_WEB_USE_SKIA='))) { + dartDefinesSet.removeWhere((String d) => d.startsWith('FLUTTER_WEB_USE_SKIA=')); + } + dartDefinesSet.addAll(webRenderer.dartDefines); + return dartDefinesSet.toList(); + } + + Map extractWebHeaders() { final Map webHeaders = {}; diff --git a/packages/flutter_tools/lib/src/test/web_test_compiler.dart b/packages/flutter_tools/lib/src/test/web_test_compiler.dart index 706759004a5..ecf28ae080f 100644 --- a/packages/flutter_tools/lib/src/test/web_test_compiler.dart +++ b/packages/flutter_tools/lib/src/test/web_test_compiler.dart @@ -69,7 +69,7 @@ class WebTestCompiler { } final String platformDillPath = _fileSystem.path.join( - _artifacts.getHostArtifact(HostArtifact.webPlatformKernelFolder).path, + getWebPlatformBinariesDirectory(_artifacts, buildInfo.webRenderer).path, platformDillName ); diff --git a/packages/flutter_tools/lib/src/web/compile.dart b/packages/flutter_tools/lib/src/web/compile.dart index dd92d49d625..c5fc910feaa 100644 --- a/packages/flutter_tools/lib/src/web/compile.dart +++ b/packages/flutter_tools/lib/src/web/compile.dart @@ -24,6 +24,7 @@ import '../version.dart'; import 'compiler_config.dart'; import 'file_generators/flutter_service_worker_js.dart'; import 'migrations/scrub_generated_plugin_registrant.dart'; +import 'web_constants.dart'; export 'compiler_config.dart'; @@ -66,14 +67,23 @@ class WebBuilder { String target, BuildInfo buildInfo, ServiceWorkerStrategy serviceWorkerStrategy, { - required List compilerConfigs, + required WebCompilerConfig compilerConfig, String? baseHref, String? outputDirectoryPath, }) async { + if (compilerConfig.isWasm) { + globals.logger.printBox( + title: 'Experimental feature', + ''' + WebAssembly compilation is experimental. + $kWasmMoreInfo''', + ); + } + final bool hasWebPlugins = (await findPlugins(flutterProject)).any((Plugin p) => p.platforms.containsKey(WebPlugin.kConfigKey)); final Directory outputDirectory = outputDirectoryPath == null - ? _fileSystem.directory(getWebBuildDirectory()) + ? _fileSystem.directory(getWebBuildDirectory(compilerConfig.isWasm)) : _fileSystem.directory(outputDirectoryPath); outputDirectory.createSync(recursive: true); @@ -89,7 +99,11 @@ class WebBuilder { final Stopwatch sw = Stopwatch()..start(); try { final BuildResult result = await _buildSystem.build( - globals.buildTargets.webServiceWorker(_fileSystem, compilerConfigs), + globals.buildTargets.webServiceWorker( + _fileSystem, + webRenderer: buildInfo.webRenderer, + isWasm: compilerConfig.isWasm, + ), Environment( projectDir: _fileSystem.currentDirectory, outputDir: outputDirectory, @@ -99,6 +113,7 @@ class WebBuilder { kHasWebPlugins: hasWebPlugins.toString(), if (baseHref != null) kBaseHref: baseHref, kServiceWorkerStrategy: serviceWorkerStrategy.cliName, + ...compilerConfig.toBuildSystemEnvironment(), ...buildInfo.toBuildSystemEnvironment(), }, artifacts: globals.artifacts!, @@ -131,7 +146,8 @@ class WebBuilder { } final String buildSettingsString = _buildEventAnalyticsSettings( - configs: compilerConfigs, + config: compilerConfig, + buildInfo: buildInfo, ); BuildEvent( @@ -147,15 +163,14 @@ class WebBuilder { )); final Duration elapsedDuration = sw.elapsed; - final String variableName = compilerConfigs.length > 1 ? 'dual-compile' : 'dart2js'; _flutterUsage.sendTiming( 'build', - variableName, + compilerConfig.isWasm ? 'dart2wasm' : 'dart2js', elapsedDuration, ); _analytics.send(Event.timing( workflow: 'build', - variableName: variableName, + variableName: compilerConfig.isWasm ? 'dart2wasm' : 'dart2js', elapsedMilliseconds: elapsedDuration.inMilliseconds, )); } @@ -242,18 +257,13 @@ const Map> kDartSdkJsMapArtif }; String _buildEventAnalyticsSettings({ - required List configs, + required WebCompilerConfig config, + required BuildInfo buildInfo, }) { - final Map values = {}; - final List renderers = []; - final List targets = []; - for (final WebCompilerConfig config in configs) { - values.addAll(config.buildEventAnalyticsValues); - renderers.add(config.renderer.name); - targets.add(config.compileTarget.name); - } - values['web-renderer'] = renderers.join(','); - values['web-target'] = targets.join(','); + final Map values = { + ...config.buildEventAnalyticsValues, + 'web-renderer': buildInfo.webRenderer.cliName, + }; final List sortedList = values.entries .map((MapEntry e) => '${e.key}: ${e.value};') diff --git a/packages/flutter_tools/lib/src/web/compiler_config.dart b/packages/flutter_tools/lib/src/web/compiler_config.dart index 676c8dcc39b..286725b6048 100644 --- a/packages/flutter_tools/lib/src/web/compiler_config.dart +++ b/packages/flutter_tools/lib/src/web/compiler_config.dart @@ -3,48 +3,58 @@ // found in the LICENSE file. import '../base/utils.dart'; -import '../convert.dart'; -import 'compile.dart'; -enum CompileTarget { - js, - wasm, -} +abstract class WebCompilerConfig { + const WebCompilerConfig(); -sealed class WebCompilerConfig { - const WebCompilerConfig({required this.renderer}); + /// Returns `true` if `this` represents configuration for the Wasm compiler. + /// + /// Otherwise, `false`–represents the JavaScript compiler. + bool get isWasm; - /// Returns which target this compiler outputs (js or wasm) - CompileTarget get compileTarget; - final WebRendererMode renderer; + Map toBuildSystemEnvironment(); - String get buildKey; - - Map get buildEventAnalyticsValues => {}; + Map get buildEventAnalyticsValues => { + 'wasm-compile': isWasm, + }; } /// Configuration for the Dart-to-Javascript compiler (dart2js). class JsCompilerConfig extends WebCompilerConfig { const JsCompilerConfig({ - this.csp = false, - this.dumpInfo = false, - this.nativeNullAssertions = false, - this.optimizationLevel = kDart2jsDefaultOptimizationLevel, - this.noFrequencyBasedMinification = false, - this.sourceMaps = true, - super.renderer = WebRendererMode.auto, + required this.csp, + required this.dumpInfo, + required this.nativeNullAssertions, + required this.optimizationLevel, + required this.noFrequencyBasedMinification, + required this.sourceMaps, }); /// Instantiates [JsCompilerConfig] suitable for the `flutter run` command. - const JsCompilerConfig.run({ - required bool nativeNullAssertions, - required WebRendererMode renderer, - }) : this( + const JsCompilerConfig.run({required bool nativeNullAssertions}) + : this( + csp: false, + dumpInfo: false, nativeNullAssertions: nativeNullAssertions, + noFrequencyBasedMinification: false, optimizationLevel: kDart2jsDefaultOptimizationLevel, - renderer: renderer, + sourceMaps: true, ); + /// Creates a new [JsCompilerConfig] from build system environment values. + /// + /// Should correspond exactly with [toBuildSystemEnvironment]. + factory JsCompilerConfig.fromBuildSystemEnvironment( + Map defines) => + JsCompilerConfig( + csp: defines[kCspMode] == 'true', + dumpInfo: defines[kDart2jsDumpInfo] == 'true', + nativeNullAssertions: defines[kNativeNullAssertions] == 'true', + optimizationLevel: defines[kDart2jsOptimization] ?? kDart2jsDefaultOptimizationLevel, + noFrequencyBasedMinification: defines[kDart2jsNoFrequencyBasedMinification] == 'true', + sourceMaps: defines[kSourceMapsEnabled] == 'true', + ); + /// The default optimization level for dart2js. /// /// Maps to [kDart2jsOptimization]. @@ -92,7 +102,17 @@ class JsCompilerConfig extends WebCompilerConfig { final bool sourceMaps; @override - CompileTarget get compileTarget => CompileTarget.js; + bool get isWasm => false; + + @override + Map toBuildSystemEnvironment() => { + kCspMode: csp.toString(), + kDart2jsDumpInfo: dumpInfo.toString(), + kNativeNullAssertions: nativeNullAssertions.toString(), + kDart2jsNoFrequencyBasedMinification: noFrequencyBasedMinification.toString(), + kDart2jsOptimization: optimizationLevel, + kSourceMapsEnabled: sourceMaps.toString(), + }; /// Arguments to use in both phases: full JS compile and CFE-only. List toSharedCommandOptions() => [ @@ -110,29 +130,25 @@ class JsCompilerConfig extends WebCompilerConfig { if (noFrequencyBasedMinification) '--no-frequency-based-minification', if (csp) '--csp', ]; - - @override - String get buildKey { - final Map settings = { - 'csp': csp, - 'dumpInfo': dumpInfo, - 'nativeNullAssertions': nativeNullAssertions, - 'noFrequencyBasedMinification': noFrequencyBasedMinification, - 'optimizationLevel': optimizationLevel, - 'sourceMaps': sourceMaps, - }; - return jsonEncode(settings); - } } /// Configuration for the Wasm compiler. class WasmCompilerConfig extends WebCompilerConfig { const WasmCompilerConfig({ - this.omitTypeChecks = false, - this.wasmOpt = WasmOptLevel.defaultValue, - super.renderer = WebRendererMode.auto, + required this.omitTypeChecks, + required this.wasmOpt, }); + /// Creates a new [WasmCompilerConfig] from build system environment values. + /// + /// Should correspond exactly with [toBuildSystemEnvironment]. + factory WasmCompilerConfig.fromBuildSystemEnvironment( + Map defines) => + WasmCompilerConfig( + omitTypeChecks: defines[kOmitTypeChecks] == 'true', + wasmOpt: WasmOptLevel.values.byName(defines[kRunWasmOpt]!), + ); + /// Build environment for [omitTypeChecks]. static const String kOmitTypeChecks = 'WasmOmitTypeChecks'; @@ -146,31 +162,25 @@ class WasmCompilerConfig extends WebCompilerConfig { final WasmOptLevel wasmOpt; @override - CompileTarget get compileTarget => CompileTarget.wasm; + bool get isWasm => true; - bool get runWasmOpt => - wasmOpt == WasmOptLevel.full || wasmOpt == WasmOptLevel.debug; + bool get runWasmOpt => wasmOpt == WasmOptLevel.full || wasmOpt == WasmOptLevel.debug; + + @override + Map toBuildSystemEnvironment() => { + kOmitTypeChecks: omitTypeChecks.toString(), + kRunWasmOpt: wasmOpt.name, + }; List toCommandOptions() => [ - if (omitTypeChecks) '--omit-type-checks', - ]; + if (omitTypeChecks) '--omit-type-checks', + ]; @override Map get buildEventAnalyticsValues => { - ...super.buildEventAnalyticsValues, - kOmitTypeChecks: omitTypeChecks.toString(), - kRunWasmOpt: wasmOpt.name, - }; - - @override - String get buildKey { - final Map settings = { - 'omitTypeChecks': omitTypeChecks, - 'wasmOpt': wasmOpt.name, - }; - return jsonEncode(settings); - } - + ...super.buildEventAnalyticsValues, + ...toBuildSystemEnvironment(), + }; } enum WasmOptLevel implements CliEnum { @@ -185,11 +195,8 @@ enum WasmOptLevel implements CliEnum { @override String get helpText => switch (this) { - WasmOptLevel.none => - 'wasm-opt is not run. Fastest build; bigger, slower output.', - WasmOptLevel.debug => - 'Similar to `${WasmOptLevel.full.name}`, but member names are preserved. Debugging is easier, but size is a bit bigger.', - WasmOptLevel.full => - 'wasm-opt is run. Build time is slower, but output is smaller and faster.', - }; + WasmOptLevel.none => 'wasm-opt is not run. Fastest build; bigger, slower output.', + WasmOptLevel.debug => 'Similar to `${WasmOptLevel.full.name}`, but member names are preserved. Debugging is easier, but size is a bit bigger.', + WasmOptLevel.full => 'wasm-opt is run. Build time is slower, but output is smaller and faster.', + }; } diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart index 15a8ed0e221..073bc90dfb5 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart @@ -11,13 +11,11 @@ import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/process.dart'; import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_system/build_system.dart'; -import 'package:flutter_tools/src/build_system/targets/web.dart'; import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/commands/build.dart'; import 'package:flutter_tools/src/commands/build_web.dart'; import 'package:flutter_tools/src/features.dart'; import 'package:flutter_tools/src/runner/flutter_command.dart'; -import 'package:flutter_tools/src/web/compile.dart'; import '../../src/common.dart'; import '../../src/context.dart'; @@ -149,9 +147,15 @@ void main() { expect(environment.defines, { 'TargetFile': 'lib/main.dart', 'HasWebPlugins': 'true', + 'cspMode': 'false', + 'SourceMaps': 'false', + 'NativeNullAssertions': 'true', 'ServiceWorkerStrategy': 'offline-first', + 'Dart2jsDumpInfo': 'false', + 'Dart2jsNoFrequencyBasedMinification': 'false', + 'Dart2jsOptimization': 'O3', 'BuildMode': 'release', - 'DartDefines': 'Zm9vPWE=', + 'DartDefines': 'Zm9vPWE=,RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==', 'DartObfuscation': 'false', 'TrackWidgetCreation': 'false', 'TreeShakeIcons': 'true', @@ -245,8 +249,15 @@ void main() { expect(environment.defines, { 'TargetFile': 'lib/main.dart', 'HasWebPlugins': 'true', + 'cspMode': 'false', + 'SourceMaps': 'false', + 'NativeNullAssertions': 'true', 'ServiceWorkerStrategy': 'offline-first', + 'Dart2jsDumpInfo': 'false', + 'Dart2jsNoFrequencyBasedMinification': 'false', + 'Dart2jsOptimization': 'O4', 'BuildMode': 'release', + 'DartDefines': 'RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==', 'DartObfuscation': 'false', 'TrackWidgetCreation': 'false', 'TreeShakeIcons': 'true', @@ -277,17 +288,15 @@ void main() { final CommandRunner runner = createTestCommandRunner(buildCommand); setupFileSystemForEndToEndTest(fileSystem); await runner.run(['build', 'web', '--no-pub']); + final BuildInfo buildInfo = + await buildCommand.webCommand.getBuildInfo(forcedBuildMode: BuildMode.debug); + expect(buildInfo.dartDefines, contains('FLUTTER_WEB_AUTO_DETECT=true')); }, overrides: { Platform: () => fakePlatform, FileSystem: () => fileSystem, FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), ProcessManager: () => processManager, - BuildSystem: () => TestBuildSystem.all(BuildResult(success: true), (Target target, Environment environment) { - expect(target, isA()); - final List configs = (target as WebServiceWorker).compileConfigs; - expect(configs.length, 1); - expect(configs.first.renderer, WebRendererMode.auto); - }), + BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)), }); testUsingContext('Web build supports build-name and build-number', () async { diff --git a/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart index 47951c7b906..bcc218c7889 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart @@ -32,6 +32,7 @@ import 'package:flutter_tools/src/resident_runner.dart'; import 'package:flutter_tools/src/run_hot.dart'; import 'package:flutter_tools/src/runner/flutter_command.dart'; import 'package:flutter_tools/src/vmservice.dart'; +import 'package:flutter_tools/src/web/compile.dart'; import 'package:test/fake.dart'; import 'package:unified_analytics/unified_analytics.dart' as analytics; import 'package:vm_service/vm_service.dart'; @@ -1086,6 +1087,47 @@ void main() { }); }); + group('dart-defines and web-renderer options', () { + late List dartDefines; + + setUp(() { + dartDefines = []; + }); + + test('auto web-renderer with no dart-defines', () { + dartDefines = FlutterCommand.updateDartDefines(dartDefines, WebRendererMode.auto); + expect(dartDefines, ['FLUTTER_WEB_AUTO_DETECT=true']); + }); + + test('canvaskit web-renderer with no dart-defines', () { + dartDefines = FlutterCommand.updateDartDefines(dartDefines, WebRendererMode.canvaskit); + expect(dartDefines, ['FLUTTER_WEB_AUTO_DETECT=false','FLUTTER_WEB_USE_SKIA=true']); + }); + + test('html web-renderer with no dart-defines', () { + dartDefines = FlutterCommand.updateDartDefines(dartDefines, WebRendererMode.html); + expect(dartDefines, ['FLUTTER_WEB_AUTO_DETECT=false','FLUTTER_WEB_USE_SKIA=false']); + }); + + test('auto web-renderer with existing dart-defines', () { + dartDefines = ['FLUTTER_WEB_USE_SKIA=false']; + dartDefines = FlutterCommand.updateDartDefines(dartDefines, WebRendererMode.auto); + expect(dartDefines, ['FLUTTER_WEB_AUTO_DETECT=true']); + }); + + test('canvaskit web-renderer with no dart-defines', () { + dartDefines = ['FLUTTER_WEB_USE_SKIA=false']; + dartDefines = FlutterCommand.updateDartDefines(dartDefines, WebRendererMode.canvaskit); + expect(dartDefines, ['FLUTTER_WEB_AUTO_DETECT=false','FLUTTER_WEB_USE_SKIA=true']); + }); + + test('html web-renderer with no dart-defines', () { + dartDefines = ['FLUTTER_WEB_USE_SKIA=true']; + dartDefines = FlutterCommand.updateDartDefines(dartDefines, WebRendererMode.html); + expect(dartDefines, ['FLUTTER_WEB_AUTO_DETECT=false','FLUTTER_WEB_USE_SKIA=false']); + }); + }); + group('terminal', () { late FakeAnsiTerminal fakeTerminal; diff --git a/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart index 212f051b3a0..d99939ded31 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart @@ -23,7 +23,6 @@ import 'package:flutter_tools/src/test/test_device.dart'; import 'package:flutter_tools/src/test/test_time_recorder.dart'; import 'package:flutter_tools/src/test/test_wrapper.dart'; import 'package:flutter_tools/src/test/watcher.dart'; -import 'package:flutter_tools/src/web/compile.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:vm_service/vm_service.dart'; @@ -1059,24 +1058,6 @@ dev_dependencies: FileSystem: () => fs, ProcessManager: () => FakeProcessManager.any(), }); - - testUsingContext('Passes web renderer into debugging options', () async { - final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0); - - final TestCommand testCommand = TestCommand(testRunner: testRunner); - final CommandRunner commandRunner = createTestCommandRunner(testCommand); - - await commandRunner.run(const [ - 'test', - '--no-pub', - '--platform=chrome', - '--web-renderer=canvaskit', - ]); - expect(testRunner.lastDebuggingOptionsValue.webRenderer, WebRendererMode.canvaskit); - }, overrides: { - FileSystem: () => fs, - ProcessManager: () => FakeProcessManager.any(), - }); }); } diff --git a/packages/flutter_tools/test/general.shard/build_system/build_system_test.dart b/packages/flutter_tools/test/general.shard/build_system/build_system_test.dart index a5c67ab92f4..22bfa2ae942 100644 --- a/packages/flutter_tools/test/general.shard/build_system/build_system_test.dart +++ b/packages/flutter_tools/test/general.shard/build_system/build_system_test.dart @@ -21,10 +21,10 @@ import '../../src/fake_process_manager.dart'; void main() { late FileSystem fileSystem; late Environment environment; - late TestTarget fooTarget; - late TestTarget barTarget; - late TestTarget fizzTarget; - late TestTarget sharedTarget; + late Target fooTarget; + late Target barTarget; + late Target fizzTarget; + late Target sharedTarget; late int fooInvocations; late int barInvocations; late int shared; @@ -138,23 +138,6 @@ void main() { json.decode(stampFile.readAsStringSync())); expect(stampContents, containsPair('inputs', ['/foo.dart'])); - expect(stampContents!.containsKey('buildKey'), false); - }); - - testWithoutContext('Saves a stamp file with inputs, outputs and build key', () async { - fooTarget.buildKey = 'fooBuildKey'; - final BuildSystem buildSystem = setUpBuildSystem(fileSystem); - await buildSystem.build(fooTarget, environment); - final File stampFile = fileSystem.file( - '${environment.buildDir.path}/foo.stamp'); - - expect(stampFile, exists); - - final Map? stampContents = castStringKeyedMap( - json.decode(stampFile.readAsStringSync())); - - expect(stampContents, containsPair('inputs', ['/foo.dart'])); - expect(stampContents, containsPair('buildKey', 'fooBuildKey')); }); testWithoutContext('Creates a BuildResult with inputs and outputs', () async { @@ -185,19 +168,6 @@ void main() { expect(fooInvocations, 2); }); - testWithoutContext('Re-invoke build if build key is modified', () async { - final BuildSystem buildSystem = setUpBuildSystem(fileSystem); - fooTarget.buildKey = 'old'; - - await buildSystem.build(fooTarget, environment); - - fooTarget.buildKey = 'new'; - - await buildSystem.build(fooTarget, environment); - - expect(fooInvocations, 2); - }); - testWithoutContext('does not re-invoke build if input timestamp changes', () async { final BuildSystem buildSystem = setUpBuildSystem(fileSystem); await buildSystem.build(fooTarget, environment); @@ -753,7 +723,4 @@ class TestTarget extends Target { @override List outputs = []; - - @override - String? buildKey; } diff --git a/packages/flutter_tools/test/general.shard/build_system/targets/web_defines_test.dart b/packages/flutter_tools/test/general.shard/build_system/targets/web_defines_test.dart deleted file mode 100644 index 71e04230a18..00000000000 --- a/packages/flutter_tools/test/general.shard/build_system/targets/web_defines_test.dart +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2014 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. - -import 'package:flutter_tools/src/build_system/targets/web.dart'; -import 'package:flutter_tools/src/web/compile.dart'; -import 'package:test/test.dart'; - -void main() { - - group('dart-defines and web-renderer options', () { - late List dartDefines; - - setUp(() { - dartDefines = []; - }); - - test('auto web-renderer with no dart-defines', () { - dartDefines = updateDartDefines(dartDefines, WebRendererMode.auto); - expect(dartDefines, ['FLUTTER_WEB_AUTO_DETECT=true']); - }); - - test('canvaskit web-renderer with no dart-defines', () { - dartDefines = updateDartDefines(dartDefines, WebRendererMode.canvaskit); - expect(dartDefines, ['FLUTTER_WEB_AUTO_DETECT=false','FLUTTER_WEB_USE_SKIA=true']); - }); - - test('html web-renderer with no dart-defines', () { - dartDefines = updateDartDefines(dartDefines, WebRendererMode.html); - expect(dartDefines, ['FLUTTER_WEB_AUTO_DETECT=false','FLUTTER_WEB_USE_SKIA=false']); - }); - - test('auto web-renderer with existing dart-defines', () { - dartDefines = ['FLUTTER_WEB_USE_SKIA=false']; - dartDefines = updateDartDefines(dartDefines, WebRendererMode.auto); - expect(dartDefines, ['FLUTTER_WEB_AUTO_DETECT=true']); - }); - - test('canvaskit web-renderer with no dart-defines', () { - dartDefines = ['FLUTTER_WEB_USE_SKIA=false']; - dartDefines = updateDartDefines(dartDefines, WebRendererMode.canvaskit); - expect(dartDefines, ['FLUTTER_WEB_AUTO_DETECT=false','FLUTTER_WEB_USE_SKIA=true']); - }); - - test('html web-renderer with no dart-defines', () { - dartDefines = ['FLUTTER_WEB_USE_SKIA=true']; - dartDefines = updateDartDefines(dartDefines, WebRendererMode.html); - expect(dartDefines, ['FLUTTER_WEB_AUTO_DETECT=false','FLUTTER_WEB_USE_SKIA=false']); - }); - }); -} diff --git a/packages/flutter_tools/test/general.shard/build_system/targets/web_test.dart b/packages/flutter_tools/test/general.shard/build_system/targets/web_test.dart index c74fb25e02b..6ce8012d9e0 100644 --- a/packages/flutter_tools/test/general.shard/build_system/targets/web_test.dart +++ b/packages/flutter_tools/test/general.shard/build_system/targets/web_test.dart @@ -120,9 +120,7 @@ void main() { webResources.childFile('index.html') .createSync(recursive: true); environment.buildDir.childFile('main.dart.js').createSync(); - await WebReleaseBundle([ - const JsCompilerConfig() - ]).build(environment); + await const WebReleaseBundle(WebRendererMode.auto, isWasm: false).build(environment); expect(environment.outputDir.childFile('version.json'), exists); })); @@ -134,9 +132,7 @@ void main() { final Directory webResources = environment.projectDir.childDirectory('web'); webResources.childFile('index.html').createSync(recursive: true); environment.buildDir.childFile('main.dart.js').createSync(); - await WebReleaseBundle([ - const JsCompilerConfig() - ]).build(environment); + await const WebReleaseBundle(WebRendererMode.auto, isWasm: false).build(environment); final String versionFile = environment.outputDir .childFile('version.json') @@ -154,9 +150,7 @@ void main() { '''); environment.buildDir.childFile('main.dart.js').createSync(); - await WebReleaseBundle([ - const JsCompilerConfig() - ]).build(environment); + await const WebReleaseBundle(WebRendererMode.auto, isWasm: false).build(environment); expect(environment.outputDir.childFile('index.html').readAsStringSync(), contains('/basehreftest/')); })); @@ -169,9 +163,7 @@ void main() { '''); environment.buildDir.childFile('main.dart.js').createSync(); - await WebReleaseBundle([ - const JsCompilerConfig() - ]).build(environment); + await const WebReleaseBundle(WebRendererMode.auto, isWasm: false).build(environment); expect(environment.outputDir.childFile('index.html').readAsStringSync(), contains('/basehreftest/')); })); @@ -193,9 +185,7 @@ void main() { .writeAsStringSync('A'); environment.buildDir.childFile('main.dart.js').createSync(); - await WebReleaseBundle([ - const JsCompilerConfig() - ]).build(environment); + await const WebReleaseBundle(WebRendererMode.auto, isWasm: false).build(environment); expect(environment.outputDir.childFile('foo.txt') .readAsStringSync(), 'A'); @@ -207,9 +197,7 @@ void main() { // Update to arbitrary resource file triggers rebuild. webResources.childFile('foo.txt').writeAsStringSync('B'); - await WebReleaseBundle([ - const JsCompilerConfig() - ]).build(environment); + await const WebReleaseBundle(WebRendererMode.auto, isWasm: false).build(environment); expect(environment.outputDir.childFile('foo.txt') .readAsStringSync(), 'B'); @@ -219,36 +207,6 @@ void main() { contains('flutter_service_worker.js?v='), )); })); - - test('WebReleaseBundle copies over output files when they change', () => testbed.run(() async { - final Directory webResources = environment.projectDir.childDirectory('web'); - webResources.childFile('foo.txt') - ..createSync(recursive: true) - ..writeAsStringSync('A'); - - environment.buildDir.childFile('main.dart.wasm')..createSync()..writeAsStringSync('old wasm'); - environment.buildDir.childFile('main.dart.mjs')..createSync()..writeAsStringSync('old mjs'); - await WebReleaseBundle([ - const WasmCompilerConfig() - ]).build(environment); - expect(environment.outputDir.childFile('main.dart.wasm') - .readAsStringSync(), 'old wasm'); - expect(environment.outputDir.childFile('main.dart.mjs') - .readAsStringSync(), 'old mjs'); - - environment.buildDir.childFile('main.dart.wasm')..createSync()..writeAsStringSync('new wasm'); - environment.buildDir.childFile('main.dart.mjs')..createSync()..writeAsStringSync('new mjs'); - - await WebReleaseBundle([ - const WasmCompilerConfig() - ]).build(environment); - - expect(environment.outputDir.childFile('main.dart.wasm') - .readAsStringSync(), 'new wasm'); - expect(environment.outputDir.childFile('main.dart.mjs') - .readAsStringSync(), 'new mjs'); - })); - test('WebEntrypointTarget generates an entrypoint for a file outside of main', () => testbed.run(() async { final File mainFile = globals.fs.file(globals.fs.path.join('other', 'lib', 'main.dart')) ..createSync(recursive: true) @@ -395,7 +353,6 @@ void main() { command: [ ..._kDart2jsLinuxArgs, '-Ddart.vm.profile=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-source-maps', '-o', environment.buildDir.childFile('app.dill').absolute.path, @@ -408,7 +365,6 @@ void main() { command: [ ..._kDart2jsLinuxArgs, '-Ddart.vm.profile=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-minify', '--no-source-maps', '-O4', @@ -419,12 +375,7 @@ void main() { ] )); - await Dart2JSTarget( - const JsCompilerConfig( - csp: true, - sourceMaps: false, - ) - ).build(environment); + await Dart2JSTarget(WebRendererMode.auto).build(environment); }, overrides: { ProcessManager: () => processManager, })); @@ -436,7 +387,6 @@ void main() { command: [ ..._kDart2jsLinuxArgs, '-Ddart.vm.profile=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-source-maps', '-o', environment.buildDir.childFile('app.dill').absolute.path, @@ -449,7 +399,6 @@ void main() { command: [ ..._kDart2jsLinuxArgs, '-Ddart.vm.profile=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-minify', '--no-source-maps', '-O4', @@ -459,11 +408,7 @@ void main() { ] )); - await Dart2JSTarget( - const JsCompilerConfig( - sourceMaps: false, - ) - ).build(environment); + await Dart2JSTarget(WebRendererMode.auto).build(environment); }, overrides: { ProcessManager: () => processManager, })); @@ -476,7 +421,6 @@ void main() { ..._kDart2jsLinuxArgs, '--enable-experiment=non-nullable', '-Ddart.vm.profile=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-source-maps', '-o', environment.buildDir.childFile('app.dill').absolute.path, @@ -490,7 +434,6 @@ void main() { ..._kDart2jsLinuxArgs, '--enable-experiment=non-nullable', '-Ddart.vm.profile=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-minify', '--no-source-maps', '-O4', @@ -500,11 +443,7 @@ void main() { ] )); - await Dart2JSTarget( - const JsCompilerConfig( - sourceMaps: false, - ) - ).build(environment); + await Dart2JSTarget(WebRendererMode.auto).build(environment); }, overrides: { ProcessManager: () => processManager, })); @@ -515,7 +454,6 @@ void main() { command: [ ..._kDart2jsLinuxArgs, '-Ddart.vm.profile=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-source-maps', '-o', environment.buildDir.childFile('app.dill').absolute.path, @@ -528,7 +466,6 @@ void main() { command: [ ..._kDart2jsLinuxArgs, '-Ddart.vm.profile=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-minify', '--no-source-maps', '-O4', @@ -538,11 +475,7 @@ void main() { ] )); - await Dart2JSTarget( - const JsCompilerConfig( - sourceMaps: false, - ) - ).build(environment); + await Dart2JSTarget(WebRendererMode.auto).build(environment); }, overrides: { ProcessManager: () => processManager, })); @@ -553,7 +486,6 @@ void main() { command: [ ..._kDart2jsLinuxArgs, '-Ddart.vm.product=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-source-maps', '-o', environment.buildDir.childFile('app.dill').absolute.path, @@ -566,7 +498,6 @@ void main() { command: [ ..._kDart2jsLinuxArgs, '-Ddart.vm.product=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-source-maps', '-O4', '-o', @@ -575,11 +506,7 @@ void main() { ] )); - await Dart2JSTarget( - const JsCompilerConfig( - sourceMaps: false, - ) - ).build(environment); + await Dart2JSTarget(WebRendererMode.auto).build(environment); }, overrides: { ProcessManager: () => processManager, })); @@ -591,7 +518,6 @@ void main() { command: [ ..._kDart2jsLinuxArgs, '-Ddart.vm.product=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--native-null-assertions', '--no-source-maps', '-o', @@ -605,7 +531,6 @@ void main() { command: [ ..._kDart2jsLinuxArgs, '-Ddart.vm.product=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--native-null-assertions', '--no-source-maps', '-O4', @@ -615,12 +540,7 @@ void main() { ] )); - await Dart2JSTarget( - const JsCompilerConfig( - nativeNullAssertions: true, - sourceMaps: false, - ) - ).build(environment); + await Dart2JSTarget(WebRendererMode.auto).build(environment); }, overrides: { ProcessManager: () => processManager, })); @@ -632,7 +552,6 @@ void main() { command: [ ..._kDart2jsLinuxArgs, '-Ddart.vm.product=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-source-maps', '-o', environment.buildDir.childFile('app.dill').absolute.path, @@ -645,7 +564,6 @@ void main() { command: [ ..._kDart2jsLinuxArgs, '-Ddart.vm.product=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-source-maps', '-O3', '-o', @@ -654,12 +572,7 @@ void main() { ] )); - await Dart2JSTarget( - const JsCompilerConfig( - optimizationLevel: 'O3', - sourceMaps: false, - ) - ).build(environment); + await Dart2JSTarget(WebRendererMode.auto).build(environment); }, overrides: { ProcessManager: () => processManager, })); @@ -670,7 +583,6 @@ void main() { command: [ ..._kDart2jsLinuxArgs, '-Ddart.vm.product=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-source-maps', '-o', environment.buildDir.childFile('app.dill').absolute.path, @@ -686,7 +598,6 @@ void main() { command: [ ..._kDart2jsLinuxArgs, '-Ddart.vm.product=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-source-maps', '-O4', '-o', @@ -695,11 +606,7 @@ void main() { ] )); - await Dart2JSTarget( - const JsCompilerConfig( - sourceMaps: false, - ) - ).build(environment); + await Dart2JSTarget(WebRendererMode.auto).build(environment); expect(environment.buildDir.childFile('dart2js.d'), exists); final Depfile depfile = environment.depFileService.parse(environment.buildDir.childFile('dart2js.d')); @@ -720,7 +627,6 @@ void main() { '-Ddart.vm.product=true', '-DFOO=bar', '-DBAZ=qux', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-source-maps', '-o', environment.buildDir.childFile('app.dill').absolute.path, @@ -735,7 +641,6 @@ void main() { '-Ddart.vm.product=true', '-DFOO=bar', '-DBAZ=qux', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-source-maps', '-O4', '-o', @@ -744,11 +649,7 @@ void main() { ] )); - await Dart2JSTarget( - const JsCompilerConfig( - sourceMaps: false, - ) - ).build(environment); + await Dart2JSTarget(WebRendererMode.auto).build(environment); }, overrides: { ProcessManager: () => processManager, })); @@ -760,7 +661,6 @@ void main() { command: [ ..._kDart2jsLinuxArgs, '-Ddart.vm.product=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '-o', environment.buildDir.childFile('app.dill').absolute.path, '--packages=.dart_tool/package_config.json', @@ -772,7 +672,6 @@ void main() { command: [ ..._kDart2jsLinuxArgs, '-Ddart.vm.product=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '-O4', '-o', environment.buildDir.childFile('main.dart.js').absolute.path, @@ -780,9 +679,7 @@ void main() { ] )); - await Dart2JSTarget( - const JsCompilerConfig() - ).build(environment); + await Dart2JSTarget(WebRendererMode.auto).build(environment); }, overrides: { ProcessManager: () => processManager, })); @@ -797,7 +694,6 @@ void main() { '-Ddart.vm.profile=true', '-DFOO=bar', '-DBAZ=qux', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-source-maps', '-o', environment.buildDir.childFile('app.dill').absolute.path, @@ -812,7 +708,6 @@ void main() { '-Ddart.vm.profile=true', '-DFOO=bar', '-DBAZ=qux', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-minify', '--no-source-maps', '-O4', @@ -822,11 +717,7 @@ void main() { ] )); - await Dart2JSTarget( - const JsCompilerConfig( - sourceMaps: false, - ) - ).build(environment); + await Dart2JSTarget(WebRendererMode.auto).build(environment); }, overrides: { ProcessManager: () => processManager, })); @@ -838,7 +729,6 @@ void main() { command: [ ..._kDart2jsLinuxArgs, '-Ddart.vm.profile=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-source-maps', '-o', environment.buildDir.childFile('app.dill').absolute.path, @@ -851,7 +741,6 @@ void main() { command: [ ..._kDart2jsLinuxArgs, '-Ddart.vm.profile=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-minify', '--no-source-maps', '-O4', @@ -862,12 +751,7 @@ void main() { ] )); - await Dart2JSTarget( - const JsCompilerConfig( - dumpInfo: true, - sourceMaps: false, - ) - ).build(environment); + await Dart2JSTarget(WebRendererMode.canvaskit).build(environment); }, overrides: { ProcessManager: () => processManager, })); @@ -879,7 +763,6 @@ void main() { command: [ ..._kDart2jsLinuxArgs, '-Ddart.vm.profile=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-source-maps', '-o', environment.buildDir.childFile('app.dill').absolute.path, @@ -892,7 +775,6 @@ void main() { command: [ ..._kDart2jsLinuxArgs, '-Ddart.vm.profile=true', - '-DFLUTTER_WEB_AUTO_DETECT=true', '--no-minify', '--no-source-maps', '-O4', @@ -903,12 +785,7 @@ void main() { ] )); - await Dart2JSTarget( - const JsCompilerConfig( - noFrequencyBasedMinification: true, - sourceMaps: false, - ) - ).build(environment); + await Dart2JSTarget(WebRendererMode.canvaskit).build(environment); }, overrides: { ProcessManager: () => processManager, })); @@ -927,8 +804,6 @@ void main() { '-Ddart.vm.profile=true', '-DFOO=bar', '-DBAZ=qux', - '-DFLUTTER_WEB_AUTO_DETECT=false', - '-DFLUTTER_WEB_USE_SKIA=true', '--depfile=${depFile.absolute.path}', environment.buildDir.childFile('main.dart').absolute.path, environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path, @@ -945,11 +820,7 @@ void main() { ]) ); - await Dart2WasmTarget( - const WasmCompilerConfig( - renderer: WebRendererMode.canvaskit - ) - ).build(environment); + await Dart2WasmTarget(WebRendererMode.canvaskit).build(environment); expect(outputJsFile.existsSync(), isFalse); final File movedJsFile = environment.buildDir.childFile('main.dart.mjs'); @@ -971,8 +842,6 @@ void main() { command: [ ..._kDart2WasmLinuxArgs, '-Ddart.vm.product=true', - '-DFLUTTER_WEB_AUTO_DETECT=false', - '-DFLUTTER_WEB_USE_SKIA=true', '--omit-type-checks', '--depfile=${depFile.absolute.path}', environment.buildDir.childFile('main.dart').absolute.path, @@ -990,12 +859,7 @@ void main() { ]) ); - await Dart2WasmTarget( - const WasmCompilerConfig( - omitTypeChecks: true, - renderer: WebRendererMode.canvaskit - ) - ).build(environment); + await Dart2WasmTarget(WebRendererMode.canvaskit).build(environment); expect(outputJsFile.existsSync(), isFalse); final File movedJsFile = environment.buildDir.childFile('main.dart.mjs'); @@ -1016,8 +880,6 @@ void main() { command: [ ..._kDart2WasmLinuxArgs, '-Ddart.vm.product=true', - '-DFLUTTER_WEB_AUTO_DETECT=false', - '-DFLUTTER_WEB_USE_SKIA=true', '--depfile=${depFile.absolute.path}', environment.buildDir.childFile('main.dart').absolute.path, environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path, @@ -1032,12 +894,7 @@ void main() { environment.buildDir.childFile('main.dart.wasm').absolute.path, ])); - await Dart2WasmTarget( - const WasmCompilerConfig( - wasmOpt: WasmOptLevel.debug, - renderer: WebRendererMode.canvaskit - ) - ).build(environment); + await Dart2WasmTarget(WebRendererMode.canvaskit).build(environment); expect(outputJsFile.existsSync(), isFalse); final File movedJsFile = environment.buildDir.childFile('main.dart.mjs'); @@ -1058,19 +915,12 @@ void main() { command: [ ..._kDart2WasmLinuxArgs, '-Ddart.vm.product=true', - '-DFLUTTER_WEB_AUTO_DETECT=false', - '-DFLUTTER_WEB_USE_SKIA=true', '--depfile=${depFile.absolute.path}', environment.buildDir.childFile('main.dart').absolute.path, environment.buildDir.childFile('main.dart.wasm').absolute.path, ], onRun: (_) => outputJsFile..createSync()..writeAsStringSync('foo'))); - await Dart2WasmTarget( - const WasmCompilerConfig( - wasmOpt: WasmOptLevel.none, - renderer: WebRendererMode.canvaskit - ) - ).build(environment); + await Dart2WasmTarget(WebRendererMode.canvaskit).build(environment); }, overrides: { ProcessManager: () => processManager, })); @@ -1085,9 +935,6 @@ void main() { command: [ ..._kDart2WasmLinuxArgs, '-Ddart.vm.product=true', - '-DFLUTTER_WEB_AUTO_DETECT=false', - '-DFLUTTER_WEB_USE_SKIA=false', - '-DFLUTTER_WEB_USE_SKWASM=true', '--import-shared-memory', '--shared-memory-max-pages=32768', '--depfile=${depFile.absolute.path}', @@ -1106,11 +953,7 @@ void main() { ]) ); - await Dart2WasmTarget( - const WasmCompilerConfig( - renderer: WebRendererMode.skwasm, - ) - ).build(environment); + await Dart2WasmTarget(WebRendererMode.skwasm).build(environment); }, overrides: { ProcessManager: () => processManager, })); @@ -1158,9 +1001,7 @@ void main() { environment.outputDir.childDirectory('a').childFile('a.txt') ..createSync(recursive: true) ..writeAsStringSync('A'); - await WebServiceWorker(globals.fs, [ - const JsCompilerConfig() - ]).build(environment); + await WebServiceWorker(globals.fs, WebRendererMode.auto, isWasm: false).build(environment); expect(environment.outputDir.childFile('flutter_service_worker.js'), exists); // Contains file hash. @@ -1183,9 +1024,7 @@ void main() { .childFile('assets/index.html') ..createSync(recursive: true) ..writeAsStringSync('A'); - await WebServiceWorker(globals.fs, [ - const JsCompilerConfig() - ]).build(environment); + await WebServiceWorker(globals.fs, WebRendererMode.auto, isWasm: false).build(environment); expect(environment.outputDir.childFile('flutter_service_worker.js'), exists); // Contains the same file hash for both `/` and the root index.html file. @@ -1207,9 +1046,7 @@ void main() { environment.outputDir .childFile('main.dart.js.map') .createSync(recursive: true); - await WebServiceWorker(globals.fs, [ - const JsCompilerConfig() - ]).build(environment); + await WebServiceWorker(globals.fs, WebRendererMode.auto, isWasm: false).build(environment); // No caching of source maps. expect(environment.outputDir.childFile('flutter_service_worker.js').readAsStringSync(), @@ -1219,12 +1056,24 @@ void main() { contains('"main.dart.js"')); })); - test('WebBuiltInAssets copies over canvaskit again if the web sdk changes', () => testbed.run(() async { + test('wasm build copies and generates specific files', () => testbed.run(() async { + globals.fs.file('bin/cache/flutter_web_sdk/canvaskit/canvaskit.wasm') + .createSync(recursive: true); + + await WebBuiltInAssets(globals.fs, WebRendererMode.auto, isWasm: true).build(environment); + + expect(environment.outputDir.childFile('main.dart.js').existsSync(), true); + expect(environment.outputDir.childDirectory('canvaskit') + .childFile('canvaskit.wasm') + .existsSync(), true); + })); + + test('wasm copies over canvaskit again if the web sdk changes', () => testbed.run(() async { final File canvasKitInput = globals.fs.file('bin/cache/flutter_web_sdk/canvaskit/canvaskit.wasm') ..createSync(recursive: true); canvasKitInput.writeAsStringSync('foo', flush: true); - await WebBuiltInAssets(globals.fs).build(environment); + await WebBuiltInAssets(globals.fs, WebRendererMode.auto, isWasm: true).build(environment); final File canvasKitOutputBefore = environment.outputDir.childDirectory('canvaskit') .childFile('canvaskit.wasm'); @@ -1233,7 +1082,7 @@ void main() { canvasKitInput.writeAsStringSync('bar', flush: true); - await WebBuiltInAssets(globals.fs).build(environment); + await WebBuiltInAssets(globals.fs, WebRendererMode.auto, isWasm: true).build(environment); final File canvasKitOutputAfter = environment.outputDir.childDirectory('canvaskit') .childFile('canvaskit.wasm'); diff --git a/packages/flutter_tools/test/general.shard/web/compile_web_test.dart b/packages/flutter_tools/test/general.shard/web/compile_web_test.dart index 39a8b12e610..b3557413f84 100644 --- a/packages/flutter_tools/test/general.shard/web/compile_web_test.dart +++ b/packages/flutter_tools/test/general.shard/web/compile_web_test.dart @@ -43,11 +43,16 @@ void main() { testUsingContext('WebBuilder sets environment on success', () async { final TestBuildSystem buildSystem = TestBuildSystem.all(BuildResult(success: true), (Target target, Environment environment) { - expect(target, isA()); + final WebServiceWorker webServiceWorker = target as WebServiceWorker; + expect(webServiceWorker.isWasm, isTrue, reason: 'should be wasm'); + expect(webServiceWorker.webRenderer, WebRendererMode.auto); + expect(environment.defines, { 'TargetFile': 'target', 'HasWebPlugins': 'false', 'ServiceWorkerStrategy': ServiceWorkerStrategy.offlineFirst.cliName, + 'WasmOmitTypeChecks': 'false', + 'RunWasmOpt': 'none', 'BuildMode': 'debug', 'DartObfuscation': 'false', 'TrackWidgetCreation': 'true', @@ -72,16 +77,10 @@ void main() { 'target', BuildInfo.debug, ServiceWorkerStrategy.offlineFirst, - compilerConfigs: [ - const WasmCompilerConfig( - wasmOpt: WasmOptLevel.none, - renderer: WebRendererMode.skwasm, - ), - const JsCompilerConfig.run( - nativeNullAssertions: true, - renderer: WebRendererMode.canvaskit, - ), - ], + compilerConfig: const WasmCompilerConfig( + omitTypeChecks: false, + wasmOpt: WasmOptLevel.none, + ), ); expect(logger.statusText, contains('Compiling target for the Web...')); @@ -103,7 +102,7 @@ void main() { label: 'web-compile', parameters: CustomDimensions( buildEventSettings: - 'RunWasmOpt: none; WasmOmitTypeChecks: false; web-renderer: skwasm,canvaskit; web-target: wasm,js;', + 'RunWasmOpt: none; WasmOmitTypeChecks: false; wasm-compile: true; web-renderer: auto;', ), ), ], @@ -116,7 +115,7 @@ void main() { Event.flutterBuildInfo( label: 'web-compile', buildType: 'web', - settings: 'RunWasmOpt: none; WasmOmitTypeChecks: false; web-renderer: skwasm,canvaskit; web-target: wasm,js;', + settings: 'RunWasmOpt: none; WasmOmitTypeChecks: false; wasm-compile: true; web-renderer: auto;', ), ]), ); @@ -124,12 +123,12 @@ void main() { // Sends timing event. final TestTimingEvent timingEvent = testUsage.timings.single; expect(timingEvent.category, 'build'); - expect(timingEvent.variableName, 'dual-compile'); + expect(timingEvent.variableName, 'dart2wasm'); expect( analyticsTimingEventExists( sentEvents: fakeAnalytics.sentEvents, workflow: 'build', - variableName: 'dual-compile', + variableName: 'dart2wasm', ), true, ); @@ -162,9 +161,7 @@ void main() { 'target', BuildInfo.debug, ServiceWorkerStrategy.offlineFirst, - compilerConfigs: [ - const JsCompilerConfig.run(nativeNullAssertions: true, renderer: WebRendererMode.auto), - ] + compilerConfig: const JsCompilerConfig.run(nativeNullAssertions: true), ), throwsToolExit(message: 'Failed to compile application for the Web.')); diff --git a/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart b/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart index 143282e76a2..0a9ac22ce52 100644 --- a/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart +++ b/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart @@ -66,7 +66,6 @@ void main() { {}, {}, NullSafetyMode.unsound, - webRenderer: WebRendererMode.canvaskit, ); releaseAssetServer = ReleaseAssetServer( globals.fs.file('main.dart').uri, @@ -292,7 +291,6 @@ void main() { {}, {}, NullSafetyMode.unsound, - webRenderer: WebRendererMode.canvaskit, ); expect(webAssetServer.basePath, 'foo/bar'); @@ -312,7 +310,6 @@ void main() { {}, {}, NullSafetyMode.unsound, - webRenderer: WebRendererMode.canvaskit, ); // Defaults to "/" when there's no base element. @@ -334,7 +331,6 @@ void main() { {}, {}, NullSafetyMode.unsound, - webRenderer: WebRendererMode.canvaskit, ), throwsToolExit(), ); @@ -355,7 +351,6 @@ void main() { {}, {}, NullSafetyMode.unsound, - webRenderer: WebRendererMode.canvaskit, ), throwsToolExit(), ); @@ -689,7 +684,6 @@ void main() { extraHeaders: const {}, chromiumLauncher: null, nullSafetyMode: NullSafetyMode.unsound, - webRenderer: WebRendererMode.html, ); webDevFS.requireJS.createSync(recursive: true); webDevFS.flutterJs.createSync(recursive: true); @@ -751,6 +745,13 @@ void main() { // New SDK should be visible.. expect(await webDevFS.webAssetServer.dartSourceContents('dart_sdk.js'), 'BELLOW'); + // Toggle CanvasKit + expect(webDevFS.webAssetServer.webRenderer, WebRendererMode.html); + webDevFS.webAssetServer.webRenderer = WebRendererMode.canvaskit; + + expect(await webDevFS.webAssetServer.dartSourceContents('dart_sdk.js'), 'OL'); + expect(await webDevFS.webAssetServer.dartSourceContents('dart_sdk.js.map'), 'CHUM'); + // Generated entrypoint. expect(await webDevFS.webAssetServer.dartSourceContents('web_entrypoint.dart'), contains('GENERATED')); @@ -799,7 +800,6 @@ void main() { extraHeaders: const {}, chromiumLauncher: null, nullSafetyMode: NullSafetyMode.sound, - webRenderer: WebRendererMode.html, ); webDevFS.requireJS.createSync(recursive: true); webDevFS.flutterJs.createSync(recursive: true); @@ -861,6 +861,11 @@ void main() { // New SDK should be visible.. expect(await webDevFS.webAssetServer.dartSourceContents('dart_sdk.js'), 'BELLOW'); + // Toggle CanvasKit + webDevFS.webAssetServer.webRenderer = WebRendererMode.canvaskit; + expect(await webDevFS.webAssetServer.dartSourceContents('dart_sdk.js'), 'OL'); + expect(await webDevFS.webAssetServer.dartSourceContents('dart_sdk.js.map'), 'CHUM'); + // Generated entrypoint. expect(await webDevFS.webAssetServer.dartSourceContents('web_entrypoint.dart'), contains('GENERATED')); @@ -908,7 +913,6 @@ void main() { extraHeaders: const {}, chromiumLauncher: null, nullSafetyMode: NullSafetyMode.sound, - webRenderer: WebRendererMode.canvaskit, ); webDevFS.requireJS.createSync(recursive: true); webDevFS.stackTraceMapper.createSync(recursive: true); @@ -970,7 +974,6 @@ void main() { nullAssertions: true, nativeNullAssertions: true, nullSafetyMode: NullSafetyMode.sound, - webRenderer: WebRendererMode.canvaskit, ); webDevFS.requireJS.createSync(recursive: true); webDevFS.stackTraceMapper.createSync(recursive: true); @@ -1016,7 +1019,6 @@ void main() { extraHeaders: const {}, chromiumLauncher: null, nullSafetyMode: NullSafetyMode.sound, - webRenderer: WebRendererMode.canvaskit, ); webDevFS.requireJS.createSync(recursive: true); webDevFS.stackTraceMapper.createSync(recursive: true); @@ -1063,7 +1065,6 @@ void main() { extraHeaders: const {}, chromiumLauncher: null, nullSafetyMode: NullSafetyMode.sound, - webRenderer: WebRendererMode.auto, ); webDevFS.requireJS.createSync(recursive: true); webDevFS.stackTraceMapper.createSync(recursive: true); @@ -1111,7 +1112,6 @@ void main() { extraHeaders: const {}, chromiumLauncher: null, nullSafetyMode: NullSafetyMode.unsound, - webRenderer: WebRendererMode.canvaskit, ); webDevFS.requireJS.createSync(recursive: true); webDevFS.stackTraceMapper.createSync(recursive: true); @@ -1148,9 +1148,7 @@ void main() { null, const {}, NullSafetyMode.unsound, - webRenderer: WebRendererMode.canvaskit, - testMode: true - ); + testMode: true); expect(webAssetServer.defaultResponseHeaders['x-frame-options'], null); await webAssetServer.dispose(); @@ -1182,9 +1180,7 @@ void main() { extraHeaderKey: extraHeaderValue, }, NullSafetyMode.unsound, - webRenderer: WebRendererMode.canvaskit, - testMode: true - ); + testMode: true); expect(webAssetServer.defaultResponseHeaders[extraHeaderKey], [extraHeaderValue]); @@ -1219,7 +1215,6 @@ void main() { {}, {}, NullSafetyMode.sound, - webRenderer: WebRendererMode.canvaskit, ); expect(await webAssetServer.metadataContents('foo/main_module.ddc_merged_metadata'), null); @@ -1262,7 +1257,6 @@ void main() { extraHeaders: const {}, chromiumLauncher: null, nullSafetyMode: NullSafetyMode.unsound, - webRenderer: WebRendererMode.canvaskit, ); webDevFS.requireJS.createSync(recursive: true); webDevFS.stackTraceMapper.createSync(recursive: true); diff --git a/packages/flutter_tools/test/integration.shard/flutter_build_wasm_test.dart b/packages/flutter_tools/test/integration.shard/flutter_build_wasm_test.dart index 40716aed39e..4290db33756 100644 --- a/packages/flutter_tools/test/integration.shard/flutter_build_wasm_test.dart +++ b/packages/flutter_tools/test/integration.shard/flutter_build_wasm_test.dart @@ -51,7 +51,7 @@ void main() { final Directory appBuildDir = fileSystem.directory(fileSystem.path.join( exampleAppDir.path, 'build', - 'web', + 'web_wasm', )); for (final String filename in const [ 'flutter.js', diff --git a/packages/flutter_tools/test/web.shard/hot_reload_web_test.dart b/packages/flutter_tools/test/web.shard/hot_reload_web_test.dart index 6220347af5c..e01e0b9e1ec 100644 --- a/packages/flutter_tools/test/web.shard/hot_reload_web_test.dart +++ b/packages/flutter_tools/test/web.shard/hot_reload_web_test.dart @@ -19,7 +19,6 @@ void main() async { await _testProject(HotReloadProject(indexHtml: indexHtmlFlutterJsCallback), name: 'flutter.js (callback)'); await _testProject(HotReloadProject(indexHtml: indexHtmlFlutterJsPromisesFull), name: 'flutter.js (promises)'); await _testProject(HotReloadProject(indexHtml: indexHtmlFlutterJsPromisesShort), name: 'flutter.js (promises, short)'); - await _testProject(HotReloadProject(indexHtml: indexHtmlFlutterJsLoad), name: 'flutter.js (load)'); await _testProject(HotReloadProject(indexHtml: indexHtmlNoFlutterJs), name: 'No flutter.js'); } diff --git a/packages/flutter_tools/test/web.shard/test_data/hot_reload_index_html_samples.dart b/packages/flutter_tools/test/web.shard/test_data/hot_reload_index_html_samples.dart index 873604bf97f..b1d5d2a18dc 100644 --- a/packages/flutter_tools/test/web.shard/test_data/hot_reload_index_html_samples.dart +++ b/packages/flutter_tools/test/web.shard/test_data/hot_reload_index_html_samples.dart @@ -56,27 +56,6 @@ String indexHtmlFlutterJsPromisesFull = _generateFlutterJsIndexHtml(''' }); '''); -/// index_with_flutterjs.html -String indexHtmlFlutterJsLoad = _generateFlutterJsIndexHtml(''' - window.addEventListener('load', function(ev) { - _flutter.buildConfig = { - builds: [ - { - "compileTarget": "dartdevc", - "renderer": "html", - "mainJsPath": "main.dart.js", - } - ] - }; - // Download main.dart.js - _flutter.loader.load({ - serviceWorkerSettings: { - serviceWorkerVersion: serviceWorkerVersion, - }, - }); - }); -'''); - /// index_without_flutterjs.html String indexHtmlNoFlutterJs = '''