From a8cc95e36d397fd12350eadf03752248f067ea49 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 2 Mar 2023 14:21:50 -0800 Subject: [PATCH] flutter_tool: only enable wasm compile in master channel (#121755) flutter_tool: only enable wasm compile in master channel --- .../lib/src/commands/build_web.dart | 25 +++++++++++++++---- packages/flutter_tools/lib/src/features.dart | 19 ++++++++++++++ .../lib/src/flutter_features.dart | 3 +++ .../test/general.shard/features_test.dart | 8 +++++- .../command_output_test.dart | 2 +- .../flutter_build_wasm_test.dart | 21 ++++++++++------ packages/flutter_tools/test/src/fakes.dart | 4 +++ 7 files changed, 68 insertions(+), 14 deletions(-) diff --git a/packages/flutter_tools/lib/src/commands/build_web.dart b/packages/flutter_tools/lib/src/commands/build_web.dart index 492fdf8326e..15f7aeea353 100644 --- a/packages/flutter_tools/lib/src/commands/build_web.dart +++ b/packages/flutter_tools/lib/src/commands/build_web.dart @@ -43,10 +43,19 @@ class BuildWebCommand extends BuildSubCommand { 'to view and debug the original source code of a compiled and minified Dart ' 'application.' ); - argParser.addFlag( - 'wasm', - help: 'Compile to WebAssembly rather than Javascript (experimental).' - ); + + if (featureFlags.isFlutterWebWasmEnabled) { + argParser.addFlag( + 'wasm', + help: 'Compile to WebAssembly rather than JavaScript (experimental).', + ); + } else { + // Add the flag as hidden. Will give a helpful error message in [runCommand] below. + argParser.addFlag( + 'wasm', + hide: true, + ); + } argParser.addOption('pwa-strategy', defaultsTo: kOfflineFirst, @@ -108,6 +117,12 @@ class BuildWebCommand extends BuildSubCommand { if (!featureFlags.isWebEnabled) { throwToolExit('"build web" is not currently supported. To enable, run "flutter config --enable-web".'); } + + final bool wasmRequested = boolArg('wasm')!; + if (wasmRequested && !featureFlags.isFlutterWebWasmEnabled) { + throwToolExit('Compiling to WebAssembly (wasm) is only available on the master channel.'); + } + final FlutterProject flutterProject = FlutterProject.current(); final String target = stringArgDeprecated('target')!; final BuildInfo buildInfo = await getBuildInfo(); @@ -146,7 +161,7 @@ class BuildWebCommand extends BuildSubCommand { stringArgDeprecated('pwa-strategy')!, boolArgDeprecated('source-maps'), boolArgDeprecated('native-null-assertions'), - boolArgDeprecated('wasm'), + wasmRequested, baseHref: baseHref, dart2jsOptimization: stringArgDeprecated('dart2js-optimization') ?? kDart2jsDefaultOptimizationLevel, outputDirectoryPath: outputDirectoryPath, diff --git a/packages/flutter_tools/lib/src/features.dart b/packages/flutter_tools/lib/src/features.dart index 55a0b41f187..dcab21b2669 100644 --- a/packages/flutter_tools/lib/src/features.dart +++ b/packages/flutter_tools/lib/src/features.dart @@ -47,6 +47,9 @@ abstract class FeatureFlags { /// Whether fast single widget reloads are enabled. bool get isSingleWidgetReloadEnabled => false; + /// Whether WebAssembly compilation for Flutter Web is enabled. + bool get isFlutterWebWasmEnabled => false; + /// Whether a particular feature is enabled for the current channel. /// /// Prefer using one of the specific getters above instead of this API. @@ -64,8 +67,14 @@ const List allFeatures = [ flutterIOSFeature, flutterFuchsiaFeature, flutterCustomDevicesFeature, + flutterWebWasm, ]; +/// All current Flutter feature flags that can be configured. +/// +/// [Feature.configSetting] is not `null`. +Iterable get allConfigurableFeatures => allFeatures.where((Feature feature) => feature.configSetting != null); + /// The [Feature] for flutter web. const Feature flutterWebFeature = Feature.fullyEnabled( name: 'Flutter for web', @@ -145,6 +154,16 @@ const Feature singleWidgetReload = Feature( ), ); +/// Enabling WebAssembly compilation from `flutter build web` +const Feature flutterWebWasm = Feature( + name: 'WebAssembly compilation from flutter build web', + environmentOverride: 'FLUTTER_WEB_WASM', + master: FeatureChannelSetting( + available: true, + enabledByDefault: true, + ), +); + /// A [Feature] is a process for conditionally enabling tool features. /// /// All settings are optional, and if not provided will generally default to diff --git a/packages/flutter_tools/lib/src/flutter_features.dart b/packages/flutter_tools/lib/src/flutter_features.dart index 9f4ce259850..672a81855d4 100644 --- a/packages/flutter_tools/lib/src/flutter_features.dart +++ b/packages/flutter_tools/lib/src/flutter_features.dart @@ -47,6 +47,9 @@ class FlutterFeatureFlags implements FeatureFlags { @override bool get isSingleWidgetReloadEnabled => isEnabled(singleWidgetReload); + @override + bool get isFlutterWebWasmEnabled => isEnabled(flutterWebWasm); + @override bool isEnabled(Feature feature) { final String currentChannel = _flutterVersion.channel; diff --git a/packages/flutter_tools/test/general.shard/features_test.dart b/packages/flutter_tools/test/general.shard/features_test.dart index 569ff1699d6..9db086ad274 100644 --- a/packages/flutter_tools/test/general.shard/features_test.dart +++ b/packages/flutter_tools/test/general.shard/features_test.dart @@ -20,7 +20,7 @@ void main() { testConfig = Config.test(); platform = FakePlatform(environment: {}); - for (final Feature feature in allFeatures) { + for (final Feature feature in allConfigurableFeatures) { testConfig.setValue(feature.configSetting!, false); } @@ -81,6 +81,12 @@ void main() { expect(featureFlags.isWebEnabled, true); }); + testWithoutContext('Flutter web wasm only enable on master', () { + expect(flutterWebWasm.getSettingForChannel('master').enabledByDefault, isTrue); + expect(flutterWebWasm.getSettingForChannel('beta').enabledByDefault, isFalse); + expect(flutterWebWasm.getSettingForChannel('stable').enabledByDefault, isFalse); + }); + testWithoutContext('Flutter web help string', () { expect(flutterWebFeature.generateHelpMessage(), 'Enable or disable Flutter for web. ' diff --git a/packages/flutter_tools/test/integration.shard/command_output_test.dart b/packages/flutter_tools/test/integration.shard/command_output_test.dart index 158f3480776..e693ff1fe59 100644 --- a/packages/flutter_tools/test/integration.shard/command_output_test.dart +++ b/packages/flutter_tools/test/integration.shard/command_output_test.dart @@ -80,7 +80,7 @@ void main() { // contains all of the experiments in features.dart expect((result.stdout as String).split('\n'), containsAll([ - for (final Feature feature in allFeatures) + for (final Feature feature in allConfigurableFeatures) contains(feature.configSetting), ])); }); 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 d7db8169f55..593aeb3c149 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 @@ -6,6 +6,7 @@ import 'dart:io'; import 'package:file_testing/file_testing.dart'; import 'package:flutter_tools/src/base/file_system.dart'; +import 'package:flutter_tools/src/features.dart'; import '../src/common.dart'; import 'test_utils.dart'; @@ -33,18 +34,24 @@ void main() { }); test('building web with --wasm produces expected files', () async { - final ProcessResult result = processManager.runSync([ - flutterBin, - 'build', - 'web', - '--wasm', - ], workingDirectory: exampleAppDir.path); + final ProcessResult result = processManager.runSync( + [ + flutterBin, + 'build', + 'web', + '--wasm', + ], + workingDirectory: exampleAppDir.path, + environment: { + flutterWebWasm.environmentOverride!: 'true' + }, + ); expect(result.exitCode, 0); final Directory appBuildDir = fileSystem.directory(fileSystem.path.join( exampleAppDir.path, 'build', - 'web_wasm' + 'web_wasm', )); for (final String filename in const [ 'flutter.js', diff --git a/packages/flutter_tools/test/src/fakes.dart b/packages/flutter_tools/test/src/fakes.dart index 87f9f1f8374..4bb5733e751 100644 --- a/packages/flutter_tools/test/src/fakes.dart +++ b/packages/flutter_tools/test/src/fakes.dart @@ -413,6 +413,7 @@ class TestFeatureFlags implements FeatureFlags { this.isIOSEnabled = true, this.isFuchsiaEnabled = false, this.areCustomDevicesEnabled = false, + this.isFlutterWebWasmEnabled = false, }); @override @@ -442,6 +443,9 @@ class TestFeatureFlags implements FeatureFlags { @override final bool areCustomDevicesEnabled; + @override + final bool isFlutterWebWasmEnabled; + @override bool isEnabled(Feature feature) { switch (feature) {