mirror of
https://github.com/flutter/flutter
synced 2024-09-12 21:01:59 +00:00
Dual compile reland (#143262)
This is an attempt at a reland of https://github.com/flutter/flutter/pull/141396 The main changes here that are different than the original PR is fixes to wire up the `flutter test` command properly with the web renderer.
This commit is contained in:
parent
4f1fc5a883
commit
5a9fa1e7bf
|
@ -6,8 +6,12 @@ found in the LICENSE file. -->
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Web Benchmarks</title>
|
<title>Web Benchmarks</title>
|
||||||
|
<script src="flutter.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script src="main.dart.js" type="application/javascript"></script>
|
<script>
|
||||||
|
{{flutter_build_config}}
|
||||||
|
_flutter.loader.load();
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -39,7 +39,7 @@ Future<TaskResult> runWebBenchmark(WebBenchmarkOptions benchmarkOptions) async {
|
||||||
'--omit-type-checks',
|
'--omit-type-checks',
|
||||||
],
|
],
|
||||||
'--dart-define=FLUTTER_WEB_ENABLE_PROFILING=true',
|
'--dart-define=FLUTTER_WEB_ENABLE_PROFILING=true',
|
||||||
'--web-renderer=${benchmarkOptions.webRenderer}',
|
if (!benchmarkOptions.useWasm) '--web-renderer=${benchmarkOptions.webRenderer}',
|
||||||
'--profile',
|
'--profile',
|
||||||
'--no-web-resources-cdn',
|
'--no-web-resources-cdn',
|
||||||
'-t',
|
'-t',
|
||||||
|
@ -125,7 +125,7 @@ Future<TaskResult> runWebBenchmark(WebBenchmarkOptions benchmarkOptions) async {
|
||||||
return Response.internalServerError(body: '$error');
|
return Response.internalServerError(body: '$error');
|
||||||
}
|
}
|
||||||
}).add(createBuildDirectoryHandler(
|
}).add(createBuildDirectoryHandler(
|
||||||
path.join(macrobenchmarksDirectory, 'build', benchmarkOptions.useWasm ? 'web_wasm' : 'web'),
|
path.join(macrobenchmarksDirectory, 'build', 'web'),
|
||||||
));
|
));
|
||||||
|
|
||||||
server = await io.HttpServer.bind('localhost', benchmarkServerPort);
|
server = await io.HttpServer.bind('localhost', benchmarkServerPort);
|
||||||
|
|
|
@ -5,14 +5,17 @@ found in the LICENSE file. -->
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Web Integration Tests</title>
|
<title>Web Integration Tests</title>
|
||||||
<script>
|
<script src="flutter.js"></script>
|
||||||
// Use the local CanvasKit bundle instead of the CDN to reduce test flakiness.
|
|
||||||
window.flutterConfiguration = {
|
|
||||||
canvasKitBaseUrl: "/canvaskit/"
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script src="main.dart.js"></script>
|
<script>
|
||||||
|
{{flutter_build_config}}
|
||||||
|
_flutter.loader.load({
|
||||||
|
config: {
|
||||||
|
// Use the local CanvasKit bundle instead of the CDN to reduce test flakiness.
|
||||||
|
canvasKitBaseUrl: "/canvaskit/",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -12,7 +12,6 @@ import 'base/os.dart';
|
||||||
import 'base/utils.dart';
|
import 'base/utils.dart';
|
||||||
import 'convert.dart';
|
import 'convert.dart';
|
||||||
import 'globals.dart' as globals;
|
import 'globals.dart' as globals;
|
||||||
import 'web/compile.dart';
|
|
||||||
|
|
||||||
/// Whether icon font subsetting is enabled by default.
|
/// Whether icon font subsetting is enabled by default.
|
||||||
const bool kIconTreeShakerEnabledDefault = true;
|
const bool kIconTreeShakerEnabledDefault = true;
|
||||||
|
@ -36,7 +35,6 @@ class BuildInfo {
|
||||||
List<String>? dartDefines,
|
List<String>? dartDefines,
|
||||||
this.bundleSkSLPath,
|
this.bundleSkSLPath,
|
||||||
List<String>? dartExperiments,
|
List<String>? dartExperiments,
|
||||||
this.webRenderer = WebRendererMode.auto,
|
|
||||||
required this.treeShakeIcons,
|
required this.treeShakeIcons,
|
||||||
this.performanceMeasurementFile,
|
this.performanceMeasurementFile,
|
||||||
this.packagesPath = '.dart_tool/package_config.json', // TODO(zanderso): make this required and remove the default.
|
this.packagesPath = '.dart_tool/package_config.json', // TODO(zanderso): make this required and remove the default.
|
||||||
|
@ -131,9 +129,6 @@ class BuildInfo {
|
||||||
/// A list of Dart experiments.
|
/// A list of Dart experiments.
|
||||||
final List<String> dartExperiments;
|
final List<String> 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
|
/// The name of a file where flutter assemble will output performance
|
||||||
/// information in a JSON format.
|
/// information in a JSON format.
|
||||||
///
|
///
|
||||||
|
@ -803,10 +798,6 @@ HostPlatform getCurrentHostPlatform() {
|
||||||
return HostPlatform.linux_x64;
|
return HostPlatform.linux_x64;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileSystemEntity getWebPlatformBinariesDirectory(Artifacts artifacts, WebRendererMode webRenderer) {
|
|
||||||
return artifacts.getHostArtifact(HostArtifact.webPlatformKernelFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the top-level build output directory.
|
/// Returns the top-level build output directory.
|
||||||
String getBuildDirectory([Config? config, FileSystem? fileSystem]) {
|
String getBuildDirectory([Config? config, FileSystem? fileSystem]) {
|
||||||
// TODO(johnmccutchan): Stop calling this function as part of setting
|
// TODO(johnmccutchan): Stop calling this function as part of setting
|
||||||
|
@ -849,8 +840,8 @@ String getMacOSBuildDirectory() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the web build output directory.
|
/// Returns the web build output directory.
|
||||||
String getWebBuildDirectory([bool isWasm = false]) {
|
String getWebBuildDirectory() {
|
||||||
return globals.fs.path.join(getBuildDirectory(), isWasm ? 'web_wasm' : 'web');
|
return globals.fs.path.join(getBuildDirectory(), 'web');
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the Linux build output directory.
|
/// Returns the Linux build output directory.
|
||||||
|
|
|
@ -136,6 +136,15 @@ abstract class Target {
|
||||||
/// A list of zero or more depfiles, located directly under {BUILD_DIR}.
|
/// A list of zero or more depfiles, located directly under {BUILD_DIR}.
|
||||||
List<String> get depfiles => const <String>[];
|
List<String> get depfiles => const <String>[];
|
||||||
|
|
||||||
|
/// 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].
|
/// Whether this target can be executed with the given [environment].
|
||||||
///
|
///
|
||||||
/// Returning `true` will cause [build] to be skipped. This is equivalent
|
/// Returning `true` will cause [build] to be skipped. This is equivalent
|
||||||
|
@ -156,6 +165,7 @@ abstract class Target {
|
||||||
<Node>[
|
<Node>[
|
||||||
for (final Target target in dependencies) target._toNode(environment),
|
for (final Target target in dependencies) target._toNode(environment),
|
||||||
],
|
],
|
||||||
|
buildKey,
|
||||||
environment,
|
environment,
|
||||||
inputsFiles.containsNewDepfile,
|
inputsFiles.containsNewDepfile,
|
||||||
);
|
);
|
||||||
|
@ -181,9 +191,11 @@ abstract class Target {
|
||||||
for (final File output in outputs) {
|
for (final File output in outputs) {
|
||||||
outputPaths.add(output.path);
|
outputPaths.add(output.path);
|
||||||
}
|
}
|
||||||
|
final String? key = buildKey;
|
||||||
final Map<String, Object> result = <String, Object>{
|
final Map<String, Object> result = <String, Object>{
|
||||||
'inputs': inputPaths,
|
'inputs': inputPaths,
|
||||||
'outputs': outputPaths,
|
'outputs': outputPaths,
|
||||||
|
if (key != null) 'buildKey': key,
|
||||||
};
|
};
|
||||||
if (!stamp.existsSync()) {
|
if (!stamp.existsSync()) {
|
||||||
stamp.createSync();
|
stamp.createSync();
|
||||||
|
@ -218,6 +230,7 @@ abstract class Target {
|
||||||
/// This requires constants from the [Environment] to resolve the paths of
|
/// This requires constants from the [Environment] to resolve the paths of
|
||||||
/// inputs and the output stamp.
|
/// inputs and the output stamp.
|
||||||
Map<String, Object> toJson(Environment environment) {
|
Map<String, Object> toJson(Environment environment) {
|
||||||
|
final String? key = buildKey;
|
||||||
return <String, Object>{
|
return <String, Object>{
|
||||||
'name': name,
|
'name': name,
|
||||||
'dependencies': <String>[
|
'dependencies': <String>[
|
||||||
|
@ -229,6 +242,7 @@ abstract class Target {
|
||||||
'outputs': <String>[
|
'outputs': <String>[
|
||||||
for (final File file in resolveOutputs(environment).sources) file.path,
|
for (final File file in resolveOutputs(environment).sources) file.path,
|
||||||
],
|
],
|
||||||
|
if (key != null) 'buildKey': key,
|
||||||
'stamp': _findStampFile(environment).absolute.path,
|
'stamp': _findStampFile(environment).absolute.path,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -980,49 +994,85 @@ void verifyOutputDirectories(List<File> outputs, Environment environment, Target
|
||||||
|
|
||||||
/// A node in the build graph.
|
/// A node in the build graph.
|
||||||
class Node {
|
class Node {
|
||||||
Node(
|
factory Node(
|
||||||
|
Target target,
|
||||||
|
List<File> inputs,
|
||||||
|
List<File> outputs,
|
||||||
|
List<Node> dependencies,
|
||||||
|
String? buildKey,
|
||||||
|
Environment environment,
|
||||||
|
bool missingDepfile,
|
||||||
|
) {
|
||||||
|
final File stamp = target._findStampFile(environment);
|
||||||
|
Map<String, Object?>? 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<Object?> && stampOutputs is List<Object?>) {
|
||||||
|
final Set<String> previousInputs = stampInputs.whereType<String>().toSet();
|
||||||
|
final Set<String> previousOutputs = stampOutputs.whereType<String>().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.target,
|
||||||
this.inputs,
|
this.inputs,
|
||||||
this.outputs,
|
this.outputs,
|
||||||
this.dependencies,
|
this.dependencies,
|
||||||
Environment environment,
|
this.buildKey,
|
||||||
this.missingDepfile,
|
this.missingDepfile,
|
||||||
) {
|
) : previousInputs = <String>{},
|
||||||
final File stamp = target._findStampFile(environment);
|
previousOutputs = <String>{},
|
||||||
|
previousBuildKey = null,
|
||||||
|
_dirty = true;
|
||||||
|
|
||||||
// If the stamp file doesn't exist, we haven't run this step before and
|
Node.withStamp(
|
||||||
// all inputs were added.
|
this.target,
|
||||||
if (!stamp.existsSync()) {
|
this.inputs,
|
||||||
// No stamp file, not safe to skip.
|
this.previousInputs,
|
||||||
_dirty = true;
|
this.outputs,
|
||||||
return;
|
this.previousOutputs,
|
||||||
}
|
this.dependencies,
|
||||||
final String content = stamp.readAsStringSync();
|
this.buildKey,
|
||||||
// Something went wrong writing the stamp file.
|
this.previousBuildKey,
|
||||||
if (content.isEmpty) {
|
this.missingDepfile,
|
||||||
stamp.deleteSync();
|
) : _dirty = false;
|
||||||
// Malformed stamp file, not safe to skip.
|
|
||||||
_dirty = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Map<String, Object?>? 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<Object?> && outputs is List<Object?>) {
|
|
||||||
inputs.cast<String?>().whereType<String>().forEach(previousInputs.add);
|
|
||||||
outputs.cast<String?>().whereType<String>().forEach(previousOutputs.add);
|
|
||||||
} else {
|
|
||||||
// The json is malformed in some way.
|
|
||||||
_dirty = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The resolved input files.
|
/// The resolved input files.
|
||||||
///
|
///
|
||||||
|
@ -1034,6 +1084,11 @@ class Node {
|
||||||
/// These files may not yet exist if the target hasn't run yet.
|
/// These files may not yet exist if the target hasn't run yet.
|
||||||
final List<File> outputs;
|
final List<File> 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.
|
/// Whether this node is missing a depfile.
|
||||||
///
|
///
|
||||||
/// This requires an additional pass of source resolution after the target
|
/// This requires an additional pass of source resolution after the target
|
||||||
|
@ -1047,10 +1102,15 @@ class Node {
|
||||||
final List<Node> dependencies;
|
final List<Node> dependencies;
|
||||||
|
|
||||||
/// Output file paths from the previous invocation of this build node.
|
/// Output file paths from the previous invocation of this build node.
|
||||||
final Set<String> previousOutputs = <String>{};
|
final Set<String> previousOutputs;
|
||||||
|
|
||||||
/// Input file paths from the previous invocation of this build node.
|
/// Input file paths from the previous invocation of this build node.
|
||||||
final Set<String> previousInputs = <String>{};
|
final Set<String> previousInputs;
|
||||||
|
|
||||||
|
/// The buildKey from the previous invocation of this build node.
|
||||||
|
///
|
||||||
|
/// See `buildKey` in the `Target` class for more information.
|
||||||
|
final String? previousBuildKey;
|
||||||
|
|
||||||
/// One or more reasons why a task was invalidated.
|
/// One or more reasons why a task was invalidated.
|
||||||
///
|
///
|
||||||
|
@ -1074,6 +1134,10 @@ class Node {
|
||||||
FileSystem fileSystem,
|
FileSystem fileSystem,
|
||||||
Logger logger,
|
Logger logger,
|
||||||
) {
|
) {
|
||||||
|
if (buildKey != previousBuildKey) {
|
||||||
|
_invalidate(InvalidatedReasonKind.buildKeyChanged);
|
||||||
|
_dirty = true;
|
||||||
|
}
|
||||||
final Set<String> currentOutputPaths = <String>{
|
final Set<String> currentOutputPaths = <String>{
|
||||||
for (final File file in outputs) file.path,
|
for (final File file in outputs) file.path,
|
||||||
};
|
};
|
||||||
|
@ -1173,7 +1237,8 @@ class InvalidatedReason {
|
||||||
InvalidatedReasonKind.inputChanged => 'The following inputs have updated contents: ${data.join(',')}',
|
InvalidatedReasonKind.inputChanged => 'The following inputs have updated contents: ${data.join(',')}',
|
||||||
InvalidatedReasonKind.outputChanged => 'The following outputs 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.outputMissing => 'The following outputs were missing: ${data.join(',')}',
|
||||||
InvalidatedReasonKind.outputSetChanged => 'The following outputs were removed from the output set: ${data.join(',')}'
|
InvalidatedReasonKind.outputSetChanged => 'The following outputs were removed from the output set: ${data.join(',')}',
|
||||||
|
InvalidatedReasonKind.buildKeyChanged => 'The target build key changed.',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1195,4 +1260,7 @@ enum InvalidatedReasonKind {
|
||||||
|
|
||||||
/// The set of expected output files changed.
|
/// The set of expected output files changed.
|
||||||
outputSetChanged,
|
outputSetChanged,
|
||||||
|
|
||||||
|
/// The build key changed
|
||||||
|
buildKeyChanged,
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import '../base/file_system.dart';
|
import '../base/file_system.dart';
|
||||||
import '../web/compile.dart';
|
import '../web/compiler_config.dart';
|
||||||
import './build_system.dart';
|
import './build_system.dart';
|
||||||
|
|
||||||
/// Commonly used build [Target]s.
|
/// Commonly used build [Target]s.
|
||||||
|
@ -14,11 +14,7 @@ abstract class BuildTargets {
|
||||||
Target get releaseCopyFlutterBundle;
|
Target get releaseCopyFlutterBundle;
|
||||||
Target get generateLocalizationsTarget;
|
Target get generateLocalizationsTarget;
|
||||||
Target get dartPluginRegistrantTarget;
|
Target get dartPluginRegistrantTarget;
|
||||||
Target webServiceWorker(
|
Target webServiceWorker(FileSystem fileSystem, List<WebCompilerConfig> compileConfigs);
|
||||||
FileSystem fileSystem, {
|
|
||||||
required WebRendererMode webRenderer,
|
|
||||||
required bool isWasm
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// BuildTargets that return NoOpTarget for every action.
|
/// BuildTargets that return NoOpTarget for every action.
|
||||||
|
@ -38,11 +34,7 @@ class NoOpBuildTargets extends BuildTargets {
|
||||||
Target get dartPluginRegistrantTarget => const _NoOpTarget();
|
Target get dartPluginRegistrantTarget => const _NoOpTarget();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Target webServiceWorker(
|
Target webServiceWorker(FileSystem fileSystem, List<WebCompilerConfig> compileConfigs) => const _NoOpTarget();
|
||||||
FileSystem fileSystem, {
|
|
||||||
required WebRendererMode webRenderer,
|
|
||||||
required bool isWasm,
|
|
||||||
}) => const _NoOpTarget();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A [Target] that does nothing.
|
/// A [Target] that does nothing.
|
||||||
|
|
|
@ -22,7 +22,6 @@ import '../../project.dart';
|
||||||
import '../../web/compile.dart';
|
import '../../web/compile.dart';
|
||||||
import '../../web/file_generators/flutter_service_worker_js.dart';
|
import '../../web/file_generators/flutter_service_worker_js.dart';
|
||||||
import '../../web/file_generators/main_dart.dart' as main_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 '../build_system.dart';
|
||||||
import '../depfile.dart';
|
import '../depfile.dart';
|
||||||
import '../exceptions.dart';
|
import '../exceptions.dart';
|
||||||
|
@ -95,11 +94,15 @@ class WebEntrypointTarget extends Target {
|
||||||
|
|
||||||
/// Compiles a web entry point with dart2js.
|
/// Compiles a web entry point with dart2js.
|
||||||
abstract class Dart2WebTarget extends Target {
|
abstract class Dart2WebTarget extends Target {
|
||||||
const Dart2WebTarget(this.webRenderer);
|
const Dart2WebTarget();
|
||||||
|
|
||||||
final WebRendererMode webRenderer;
|
|
||||||
Source get compilerSnapshot;
|
Source get compilerSnapshot;
|
||||||
|
|
||||||
|
WebCompilerConfig get compilerConfig;
|
||||||
|
|
||||||
|
Map<String, Object?> get buildConfig;
|
||||||
|
List<String> get buildFiles;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Target> get dependencies => const <Target>[
|
List<Target> get dependencies => const <Target>[
|
||||||
WebEntrypointTarget(),
|
WebEntrypointTarget(),
|
||||||
|
@ -116,11 +119,19 @@ abstract class Dart2WebTarget extends Target {
|
||||||
];
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Source> get outputs => const <Source>[];
|
List<Source> get outputs => buildFiles.map(
|
||||||
|
(String file) => Source.pattern('{BUILD_DIR}/$file')
|
||||||
|
).toList();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get buildKey => compilerConfig.buildKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Dart2JSTarget extends Dart2WebTarget {
|
class Dart2JSTarget extends Dart2WebTarget {
|
||||||
Dart2JSTarget(super.webRenderer);
|
Dart2JSTarget(this.compilerConfig);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final JsCompilerConfig compilerConfig;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get name => 'dart2js';
|
String get name => 'dart2js';
|
||||||
|
@ -140,9 +151,11 @@ class Dart2JSTarget extends Dart2WebTarget {
|
||||||
throw MissingDefineException(kBuildMode, name);
|
throw MissingDefineException(kBuildMode, name);
|
||||||
}
|
}
|
||||||
final BuildMode buildMode = BuildMode.fromCliName(buildModeEnvironment);
|
final BuildMode buildMode = BuildMode.fromCliName(buildModeEnvironment);
|
||||||
final JsCompilerConfig compilerConfig = JsCompilerConfig.fromBuildSystemEnvironment(environment.defines);
|
|
||||||
final Artifacts artifacts = environment.artifacts;
|
final Artifacts artifacts = environment.artifacts;
|
||||||
final String platformBinariesPath = getWebPlatformBinariesDirectory(artifacts, webRenderer).path;
|
final String platformBinariesPath = artifacts.getHostArtifact(HostArtifact.webPlatformKernelFolder).path;
|
||||||
|
final List<String> dartDefines = compilerConfig.renderer.updateDartDefines(
|
||||||
|
decodeDartDefines(environment.defines, kDartDefines),
|
||||||
|
);
|
||||||
final List<String> sharedCommandOptions = <String>[
|
final List<String> sharedCommandOptions = <String>[
|
||||||
artifacts.getArtifactPath(Artifact.engineDartBinary, platform: TargetPlatform.web_javascript),
|
artifacts.getArtifactPath(Artifact.engineDartBinary, platform: TargetPlatform.web_javascript),
|
||||||
'--disable-dart-dev',
|
'--disable-dart-dev',
|
||||||
|
@ -154,7 +167,7 @@ class Dart2JSTarget extends Dart2WebTarget {
|
||||||
'-Ddart.vm.profile=true'
|
'-Ddart.vm.profile=true'
|
||||||
else
|
else
|
||||||
'-Ddart.vm.product=true',
|
'-Ddart.vm.product=true',
|
||||||
for (final String dartDefine in decodeDartDefines(environment.defines, kDartDefines))
|
for (final String dartDefine in dartDefines)
|
||||||
'-D$dartDefine',
|
'-D$dartDefine',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -208,10 +221,25 @@ class Dart2JSTarget extends Dart2WebTarget {
|
||||||
environment.buildDir.childFile('dart2js.d'),
|
environment.buildDir.childFile('dart2js.d'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, Object?> get buildConfig => <String, Object?>{
|
||||||
|
'compileTarget': 'dart2js',
|
||||||
|
'renderer': compilerConfig.renderer.name,
|
||||||
|
'mainJsPath': 'main.dart.js',
|
||||||
|
};
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<String> get buildFiles => <String>[
|
||||||
|
'main.dart.js',
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
class Dart2WasmTarget extends Dart2WebTarget {
|
class Dart2WasmTarget extends Dart2WebTarget {
|
||||||
Dart2WasmTarget(super.webRenderer);
|
Dart2WasmTarget(this.compilerConfig);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final WasmCompilerConfig compilerConfig;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> build(Environment environment) async {
|
Future<void> build(Environment environment) async {
|
||||||
|
@ -219,7 +247,6 @@ class Dart2WasmTarget extends Dart2WebTarget {
|
||||||
if (buildModeEnvironment == null) {
|
if (buildModeEnvironment == null) {
|
||||||
throw MissingDefineException(kBuildMode, name);
|
throw MissingDefineException(kBuildMode, name);
|
||||||
}
|
}
|
||||||
final WasmCompilerConfig compilerConfig = WasmCompilerConfig.fromBuildSystemEnvironment(environment.defines);
|
|
||||||
final BuildMode buildMode = BuildMode.fromCliName(buildModeEnvironment);
|
final BuildMode buildMode = BuildMode.fromCliName(buildModeEnvironment);
|
||||||
final Artifacts artifacts = environment.artifacts;
|
final Artifacts artifacts = environment.artifacts;
|
||||||
final File outputWasmFile = environment.buildDir.childFile(
|
final File outputWasmFile = environment.buildDir.childFile(
|
||||||
|
@ -227,8 +254,11 @@ class Dart2WasmTarget extends Dart2WebTarget {
|
||||||
);
|
);
|
||||||
final File depFile = environment.buildDir.childFile('dart2wasm.d');
|
final File depFile = environment.buildDir.childFile('dart2wasm.d');
|
||||||
final String dartSdkPath = artifacts.getArtifactPath(Artifact.engineDartSdkPath, platform: TargetPlatform.web_javascript);
|
final String dartSdkPath = artifacts.getArtifactPath(Artifact.engineDartSdkPath, platform: TargetPlatform.web_javascript);
|
||||||
final String platformBinariesPath = getWebPlatformBinariesDirectory(artifacts, webRenderer).path;
|
final String platformBinariesPath = artifacts.getHostArtifact(HostArtifact.webPlatformKernelFolder).path;
|
||||||
final String platformFilePath = environment.fileSystem.path.join(platformBinariesPath, 'dart2wasm_platform.dill');
|
final String platformFilePath = environment.fileSystem.path.join(platformBinariesPath, 'dart2wasm_platform.dill');
|
||||||
|
final List<String> dartDefines = compilerConfig.renderer.updateDartDefines(
|
||||||
|
decodeDartDefines(environment.defines, kDartDefines),
|
||||||
|
);
|
||||||
|
|
||||||
final List<String> compilationArgs = <String>[
|
final List<String> compilationArgs = <String>[
|
||||||
artifacts.getArtifactPath(Artifact.engineDartAotRuntime, platform: TargetPlatform.web_javascript),
|
artifacts.getArtifactPath(Artifact.engineDartAotRuntime, platform: TargetPlatform.web_javascript),
|
||||||
|
@ -242,10 +272,10 @@ class Dart2WasmTarget extends Dart2WebTarget {
|
||||||
else
|
else
|
||||||
'-Ddart.vm.product=true',
|
'-Ddart.vm.product=true',
|
||||||
...decodeCommaSeparated(environment.defines, kExtraFrontEndOptions),
|
...decodeCommaSeparated(environment.defines, kExtraFrontEndOptions),
|
||||||
for (final String dartDefine in decodeDartDefines(environment.defines, kDartDefines))
|
for (final String dartDefine in dartDefines)
|
||||||
'-D$dartDefine',
|
'-D$dartDefine',
|
||||||
...compilerConfig.toCommandOptions(),
|
...compilerConfig.toCommandOptions(),
|
||||||
if (webRenderer == WebRendererMode.skwasm)
|
if (compilerConfig.renderer == WebRendererMode.skwasm)
|
||||||
...<String>[
|
...<String>[
|
||||||
'--import-shared-memory',
|
'--import-shared-memory',
|
||||||
'--shared-memory-max-pages=32768',
|
'--shared-memory-max-pages=32768',
|
||||||
|
@ -310,74 +340,75 @@ class Dart2WasmTarget extends Dart2WebTarget {
|
||||||
];
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Source> get outputs => const <Source>[
|
Map<String, Object?> get buildConfig => <String, Object?>{
|
||||||
Source.pattern('{OUTPUT_DIR}/main.dart.wasm'),
|
'compileTarget': 'dart2wasm',
|
||||||
Source.pattern('{OUTPUT_DIR}/main.dart.mjs'),
|
'renderer': compilerConfig.renderer.name,
|
||||||
|
'mainWasmPath': 'main.dart.wasm',
|
||||||
|
'jsSupportRuntimePath': 'main.dart.mjs',
|
||||||
|
};
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<String> get buildFiles => <String>[
|
||||||
|
'main.dart.wasm',
|
||||||
|
'main.dart.mjs',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unpacks the dart2js or dart2wasm compilation and resources to a given
|
/// Unpacks the dart2js or dart2wasm compilation and resources to a given
|
||||||
/// output directory.
|
/// output directory.
|
||||||
class WebReleaseBundle extends Target {
|
class WebReleaseBundle extends Target {
|
||||||
const WebReleaseBundle(this.webRenderer, {required this.isWasm});
|
WebReleaseBundle(List<WebCompilerConfig> configs) : this._withTargets(
|
||||||
|
configs.map((WebCompilerConfig config) =>
|
||||||
|
switch (config) {
|
||||||
|
WasmCompilerConfig() => Dart2WasmTarget(config),
|
||||||
|
JsCompilerConfig() => Dart2JSTarget(config),
|
||||||
|
}
|
||||||
|
).toList()
|
||||||
|
);
|
||||||
|
|
||||||
final WebRendererMode webRenderer;
|
const WebReleaseBundle._withTargets(this.compileTargets);
|
||||||
final bool isWasm;
|
|
||||||
|
|
||||||
String get outputFileNameNoSuffix => 'main.dart';
|
final List<Dart2WebTarget> compileTargets;
|
||||||
String get outputFileName => '$outputFileNameNoSuffix${isWasm ? '.wasm' : '.js'}';
|
|
||||||
String get wasmJSRuntimeFileName => '$outputFileNameNoSuffix.mjs';
|
List<String> get buildFiles => compileTargets.fold(
|
||||||
|
const Iterable<String>.empty(),
|
||||||
|
(Iterable<String> current, Dart2WebTarget target) => current.followedBy(target.buildFiles)
|
||||||
|
).toList();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get name => 'web_release_bundle';
|
String get name => 'web_release_bundle';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Target> get dependencies => <Target>[
|
List<Target> get dependencies => compileTargets;
|
||||||
if (isWasm) Dart2WasmTarget(webRenderer) else Dart2JSTarget(webRenderer),
|
|
||||||
];
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Source> get inputs => <Source>[
|
List<Source> get inputs => <Source>[
|
||||||
Source.pattern('{BUILD_DIR}/$outputFileName'),
|
|
||||||
const Source.pattern('{PROJECT_DIR}/pubspec.yaml'),
|
const Source.pattern('{PROJECT_DIR}/pubspec.yaml'),
|
||||||
if (isWasm) Source.pattern('{BUILD_DIR}/$wasmJSRuntimeFileName'),
|
...buildFiles.map((String file) => Source.pattern('{BUILD_DIR}/$file'))
|
||||||
];
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Source> get outputs => <Source>[
|
List<Source> get outputs => <Source>[
|
||||||
Source.pattern('{OUTPUT_DIR}/$outputFileName'),
|
...buildFiles.map((String file) => Source.pattern('{OUTPUT_DIR}/$file'))
|
||||||
if (isWasm) Source.pattern('{OUTPUT_DIR}/$wasmJSRuntimeFileName'),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<String> get depfiles => const <String>[
|
List<String> get depfiles => const <String>[
|
||||||
'dart2js.d',
|
|
||||||
'flutter_assets.d',
|
'flutter_assets.d',
|
||||||
'web_resources.d',
|
'web_resources.d',
|
||||||
];
|
];
|
||||||
|
|
||||||
bool shouldCopy(String name) =>
|
|
||||||
// Do not copy the deps file.
|
|
||||||
(name.contains(outputFileName) && !name.endsWith('.deps')) ||
|
|
||||||
(isWasm && name == wasmJSRuntimeFileName);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> build(Environment environment) async {
|
Future<void> build(Environment environment) async {
|
||||||
for (final File outputFile in environment.buildDir.listSync(recursive: true).whereType<File>()) {
|
for (final File outputFile in environment.buildDir.listSync(recursive: true).whereType<File>()) {
|
||||||
final String basename = environment.fileSystem.path.basename(outputFile.path);
|
final String basename = environment.fileSystem.path.basename(outputFile.path);
|
||||||
if (shouldCopy(basename)) {
|
if (buildFiles.contains(basename)) {
|
||||||
outputFile.copySync(
|
outputFile.copySync(
|
||||||
environment.outputDir.childFile(environment.fileSystem.path.basename(outputFile.path)).path
|
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);
|
createVersionFile(environment, environment.defines);
|
||||||
final Directory outputDirectory = environment.outputDir.childDirectory('assets');
|
final Directory outputDirectory = environment.outputDir.childDirectory('assets');
|
||||||
outputDirectory.createSync(recursive: true);
|
outputDirectory.createSync(recursive: true);
|
||||||
|
@ -413,10 +444,19 @@ class WebReleaseBundle extends Target {
|
||||||
// because it would need to be the hash for the entire bundle and not just the resource
|
// because it would need to be the hash for the entire bundle and not just the resource
|
||||||
// in question.
|
// in question.
|
||||||
if (environment.fileSystem.path.basename(inputFile.path) == 'index.html') {
|
if (environment.fileSystem.path.basename(inputFile.path) == 'index.html') {
|
||||||
|
final List<Map<String, Object?>> buildDescriptions = compileTargets.map(
|
||||||
|
(Dart2WebTarget target) => target.buildConfig
|
||||||
|
).toList();
|
||||||
|
final Map<String, Object?> buildConfig = <String, Object?>{
|
||||||
|
'engineRevision': globals.flutterVersion.engineRevision,
|
||||||
|
'builds': buildDescriptions,
|
||||||
|
};
|
||||||
|
final String buildConfigString = '_flutter.buildConfig = ${jsonEncode(buildConfig)};';
|
||||||
final IndexHtml indexHtml = IndexHtml(inputFile.readAsStringSync());
|
final IndexHtml indexHtml = IndexHtml(inputFile.readAsStringSync());
|
||||||
indexHtml.applySubstitutions(
|
indexHtml.applySubstitutions(
|
||||||
baseHref: environment.defines[kBaseHref] ?? '/',
|
baseHref: environment.defines[kBaseHref] ?? '/',
|
||||||
serviceWorkerVersion: Random().nextInt(4294967296).toString(),
|
serviceWorkerVersion: Random().nextInt(4294967296).toString(),
|
||||||
|
buildConfig: buildConfigString,
|
||||||
);
|
);
|
||||||
outputFile.writeAsStringSync(indexHtml.content);
|
outputFile.writeAsStringSync(indexHtml.content);
|
||||||
continue;
|
continue;
|
||||||
|
@ -456,11 +496,9 @@ class WebReleaseBundle extends Target {
|
||||||
/// These assets can be cached until a new version of the flutter web sdk is
|
/// These assets can be cached until a new version of the flutter web sdk is
|
||||||
/// downloaded.
|
/// downloaded.
|
||||||
class WebBuiltInAssets extends Target {
|
class WebBuiltInAssets extends Target {
|
||||||
const WebBuiltInAssets(this.fileSystem, this.webRenderer, {required this.isWasm});
|
const WebBuiltInAssets(this.fileSystem);
|
||||||
|
|
||||||
final FileSystem fileSystem;
|
final FileSystem fileSystem;
|
||||||
final WebRendererMode webRenderer;
|
|
||||||
final bool isWasm;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get name => 'web_static_assets';
|
String get name => 'web_static_assets';
|
||||||
|
@ -491,7 +529,6 @@ class WebBuiltInAssets extends Target {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Source> get outputs => <Source>[
|
List<Source> get outputs => <Source>[
|
||||||
if (isWasm) const Source.pattern('{BUILD_DIR}/main.dart.js'),
|
|
||||||
const Source.pattern('{BUILD_DIR}/flutter.js'),
|
const Source.pattern('{BUILD_DIR}/flutter.js'),
|
||||||
for (final File file in _canvasKitFiles)
|
for (final File file in _canvasKitFiles)
|
||||||
Source.pattern('{BUILD_DIR}/canvaskit/${_filePathRelativeToCanvasKitDirectory(file)}'),
|
Source.pattern('{BUILD_DIR}/canvaskit/${_filePathRelativeToCanvasKitDirectory(file)}'),
|
||||||
|
@ -505,13 +542,6 @@ class WebBuiltInAssets extends Target {
|
||||||
file.copySync(targetPath);
|
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
|
// Write the flutter.js file
|
||||||
final String flutterJsOut = fileSystem.path.join(environment.outputDir.path, 'flutter.js');
|
final String flutterJsOut = fileSystem.path.join(environment.outputDir.path, 'flutter.js');
|
||||||
final File flutterJsFile = fileSystem.file(fileSystem.path.join(
|
final File flutterJsFile = fileSystem.file(fileSystem.path.join(
|
||||||
|
@ -524,20 +554,18 @@ class WebBuiltInAssets extends Target {
|
||||||
|
|
||||||
/// Generate a service worker for a web target.
|
/// Generate a service worker for a web target.
|
||||||
class WebServiceWorker extends Target {
|
class WebServiceWorker extends Target {
|
||||||
const WebServiceWorker(this.fileSystem, this.webRenderer, {required this.isWasm});
|
const WebServiceWorker(this.fileSystem, this.compileConfigs);
|
||||||
|
|
||||||
final FileSystem fileSystem;
|
final FileSystem fileSystem;
|
||||||
final WebRendererMode webRenderer;
|
final List<WebCompilerConfig> compileConfigs;
|
||||||
final bool isWasm;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get name => 'web_service_worker';
|
String get name => 'web_service_worker';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Target> get dependencies => <Target>[
|
List<Target> get dependencies => <Target>[
|
||||||
if (isWasm) Dart2WasmTarget(webRenderer) else Dart2JSTarget(webRenderer),
|
WebReleaseBundle(compileConfigs),
|
||||||
WebReleaseBundle(webRenderer, isWasm: isWasm),
|
WebBuiltInAssets(fileSystem),
|
||||||
WebBuiltInAssets(fileSystem, webRenderer, isWasm: isWasm),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -592,6 +620,10 @@ class WebServiceWorker extends Target {
|
||||||
urlToHash,
|
urlToHash,
|
||||||
<String>[
|
<String>[
|
||||||
'main.dart.js',
|
'main.dart.js',
|
||||||
|
if (compileConfigs.any((WebCompilerConfig config) => config is WasmCompilerConfig)) ...<String>[
|
||||||
|
'main.dart.wasm',
|
||||||
|
'main.dart.mjs',
|
||||||
|
],
|
||||||
'index.html',
|
'index.html',
|
||||||
if (urlToHash.containsKey('assets/AssetManifest.bin.json'))
|
if (urlToHash.containsKey('assets/AssetManifest.bin.json'))
|
||||||
'assets/AssetManifest.bin.json',
|
'assets/AssetManifest.bin.json',
|
||||||
|
|
|
@ -138,24 +138,50 @@ class BuildWebCommand extends BuildSubCommand {
|
||||||
throwToolExit('"build web" is not currently supported. To enable, run "flutter config --enable-web".');
|
throwToolExit('"build web" is not currently supported. To enable, run "flutter config --enable-web".');
|
||||||
}
|
}
|
||||||
|
|
||||||
final WebCompilerConfig compilerConfig;
|
final List<WebCompilerConfig> compilerConfigs;
|
||||||
if (boolArg('wasm')) {
|
if (boolArg('wasm')) {
|
||||||
if (!featureFlags.isFlutterWebWasmEnabled) {
|
if (!featureFlags.isFlutterWebWasmEnabled) {
|
||||||
throwToolExit('Compiling to WebAssembly (wasm) is only available on the master channel.');
|
throwToolExit('Compiling to WebAssembly (wasm) is only available on the master channel.');
|
||||||
}
|
}
|
||||||
compilerConfig = WasmCompilerConfig(
|
if (stringArg(FlutterOptions.kWebRendererFlag) != argParser.defaultFor(FlutterOptions.kWebRendererFlag)) {
|
||||||
omitTypeChecks: boolArg('omit-type-checks'),
|
throwToolExit('"--${FlutterOptions.kWebRendererFlag}" cannot be combined with "--${FlutterOptions.kWebWasmFlag}"');
|
||||||
wasmOpt: WasmOptLevel.values.byName(stringArg('wasm-opt')!),
|
}
|
||||||
|
globals.logger.printBox(
|
||||||
|
title: 'Experimental feature',
|
||||||
|
'''
|
||||||
|
WebAssembly compilation is experimental.
|
||||||
|
$kWasmMoreInfo''',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
compilerConfigs = <WebCompilerConfig>[
|
||||||
|
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 {
|
} else {
|
||||||
compilerConfig = JsCompilerConfig(
|
WebRendererMode webRenderer = WebRendererMode.auto;
|
||||||
|
if (argParser.options.containsKey(FlutterOptions.kWebRendererFlag)) {
|
||||||
|
webRenderer = WebRendererMode.values.byName(stringArg(FlutterOptions.kWebRendererFlag)!);
|
||||||
|
}
|
||||||
|
compilerConfigs = <WebCompilerConfig>[JsCompilerConfig(
|
||||||
csp: boolArg('csp'),
|
csp: boolArg('csp'),
|
||||||
optimizationLevel: stringArg('dart2js-optimization') ?? JsCompilerConfig.kDart2jsDefaultOptimizationLevel,
|
optimizationLevel: stringArg('dart2js-optimization') ?? JsCompilerConfig.kDart2jsDefaultOptimizationLevel,
|
||||||
dumpInfo: boolArg('dump-info'),
|
dumpInfo: boolArg('dump-info'),
|
||||||
nativeNullAssertions: boolArg('native-null-assertions'),
|
nativeNullAssertions: boolArg('native-null-assertions'),
|
||||||
noFrequencyBasedMinification: boolArg('no-frequency-based-minification'),
|
noFrequencyBasedMinification: boolArg('no-frequency-based-minification'),
|
||||||
sourceMaps: boolArg('source-maps'),
|
sourceMaps: boolArg('source-maps'),
|
||||||
);
|
renderer: webRenderer,
|
||||||
|
)];
|
||||||
}
|
}
|
||||||
|
|
||||||
final FlutterProject flutterProject = FlutterProject.current();
|
final FlutterProject flutterProject = FlutterProject.current();
|
||||||
|
@ -205,7 +231,7 @@ class BuildWebCommand extends BuildSubCommand {
|
||||||
target,
|
target,
|
||||||
buildInfo,
|
buildInfo,
|
||||||
ServiceWorkerStrategy.fromCliName(stringArg('pwa-strategy')),
|
ServiceWorkerStrategy.fromCliName(stringArg('pwa-strategy')),
|
||||||
compilerConfig: compilerConfig,
|
compilerConfigs: compilerConfigs,
|
||||||
baseHref: baseHref,
|
baseHref: baseHref,
|
||||||
outputDirectoryPath: outputDirectoryPath,
|
outputDirectoryPath: outputDirectoryPath,
|
||||||
);
|
);
|
||||||
|
|
|
@ -29,6 +29,7 @@ import '../runner/flutter_command.dart';
|
||||||
import '../runner/flutter_command_runner.dart';
|
import '../runner/flutter_command_runner.dart';
|
||||||
import '../tracing.dart';
|
import '../tracing.dart';
|
||||||
import '../vmservice.dart';
|
import '../vmservice.dart';
|
||||||
|
import '../web/compile.dart';
|
||||||
import '../web/web_runner.dart';
|
import '../web/web_runner.dart';
|
||||||
import 'daemon.dart';
|
import 'daemon.dart';
|
||||||
|
|
||||||
|
@ -241,6 +242,10 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
|
||||||
final Map<String, String> webHeaders = featureFlags.isWebEnabled
|
final Map<String, String> webHeaders = featureFlags.isWebEnabled
|
||||||
? extractWebHeaders()
|
? extractWebHeaders()
|
||||||
: const <String, String>{};
|
: const <String, String>{};
|
||||||
|
final String? webRendererString = stringArg('web-renderer');
|
||||||
|
final WebRendererMode webRenderer = (webRendererString != null)
|
||||||
|
? WebRendererMode.values.byName(webRendererString)
|
||||||
|
: WebRendererMode.auto;
|
||||||
|
|
||||||
if (buildInfo.mode.isRelease) {
|
if (buildInfo.mode.isRelease) {
|
||||||
return DebuggingOptions.disabled(
|
return DebuggingOptions.disabled(
|
||||||
|
@ -258,6 +263,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
|
||||||
webBrowserDebugPort: webBrowserDebugPort,
|
webBrowserDebugPort: webBrowserDebugPort,
|
||||||
webBrowserFlags: webBrowserFlags,
|
webBrowserFlags: webBrowserFlags,
|
||||||
webHeaders: webHeaders,
|
webHeaders: webHeaders,
|
||||||
|
webRenderer: webRenderer,
|
||||||
enableImpeller: enableImpeller,
|
enableImpeller: enableImpeller,
|
||||||
enableVulkanValidation: enableVulkanValidation,
|
enableVulkanValidation: enableVulkanValidation,
|
||||||
uninstallFirst: uninstallFirst,
|
uninstallFirst: uninstallFirst,
|
||||||
|
@ -307,6 +313,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
|
||||||
webEnableExpressionEvaluation: featureFlags.isWebEnabled && boolArg('web-enable-expression-evaluation'),
|
webEnableExpressionEvaluation: featureFlags.isWebEnabled && boolArg('web-enable-expression-evaluation'),
|
||||||
webLaunchUrl: featureFlags.isWebEnabled ? stringArg('web-launch-url') : null,
|
webLaunchUrl: featureFlags.isWebEnabled ? stringArg('web-launch-url') : null,
|
||||||
webHeaders: webHeaders,
|
webHeaders: webHeaders,
|
||||||
|
webRenderer: webRenderer,
|
||||||
vmserviceOutFile: stringArg('vmservice-out-file'),
|
vmserviceOutFile: stringArg('vmservice-out-file'),
|
||||||
fastStart: argParser.options.containsKey('fast-start')
|
fastStart: argParser.options.containsKey('fast-start')
|
||||||
&& boolArg('fast-start')
|
&& boolArg('fast-start')
|
||||||
|
|
|
@ -22,6 +22,7 @@ import '../test/runner.dart';
|
||||||
import '../test/test_time_recorder.dart';
|
import '../test/test_time_recorder.dart';
|
||||||
import '../test/test_wrapper.dart';
|
import '../test/test_wrapper.dart';
|
||||||
import '../test/watcher.dart';
|
import '../test/watcher.dart';
|
||||||
|
import '../web/compile.dart';
|
||||||
|
|
||||||
/// The name of the directory where Integration Tests are placed.
|
/// The name of the directory where Integration Tests are placed.
|
||||||
///
|
///
|
||||||
|
@ -357,6 +358,10 @@ 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(
|
final DebuggingOptions debuggingOptions = DebuggingOptions.enabled(
|
||||||
buildInfo,
|
buildInfo,
|
||||||
startPaused: startPaused,
|
startPaused: startPaused,
|
||||||
|
@ -369,6 +374,7 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
|
||||||
usingCISystem: usingCISystem,
|
usingCISystem: usingCISystem,
|
||||||
enableImpeller: ImpellerStatus.fromBool(argResults!['enable-impeller'] as bool?),
|
enableImpeller: ImpellerStatus.fromBool(argResults!['enable-impeller'] as bool?),
|
||||||
debugLogsDirectoryPath: debugLogsDirectoryPath,
|
debugLogsDirectoryPath: debugLogsDirectoryPath,
|
||||||
|
webRenderer: webRenderer,
|
||||||
);
|
);
|
||||||
|
|
||||||
String? testAssetDirectory;
|
String? testAssetDirectory;
|
||||||
|
|
|
@ -18,6 +18,7 @@ import 'devfs.dart';
|
||||||
import 'device_port_forwarder.dart';
|
import 'device_port_forwarder.dart';
|
||||||
import 'project.dart';
|
import 'project.dart';
|
||||||
import 'vmservice.dart';
|
import 'vmservice.dart';
|
||||||
|
import 'web/compile.dart';
|
||||||
|
|
||||||
DeviceManager? get deviceManager => context.get<DeviceManager>();
|
DeviceManager? get deviceManager => context.get<DeviceManager>();
|
||||||
|
|
||||||
|
@ -952,6 +953,7 @@ class DebuggingOptions {
|
||||||
this.webEnableExpressionEvaluation = false,
|
this.webEnableExpressionEvaluation = false,
|
||||||
this.webHeaders = const <String, String>{},
|
this.webHeaders = const <String, String>{},
|
||||||
this.webLaunchUrl,
|
this.webLaunchUrl,
|
||||||
|
this.webRenderer = WebRendererMode.auto,
|
||||||
this.vmserviceOutFile,
|
this.vmserviceOutFile,
|
||||||
this.fastStart = false,
|
this.fastStart = false,
|
||||||
this.nullAssertions = false,
|
this.nullAssertions = false,
|
||||||
|
@ -981,6 +983,7 @@ class DebuggingOptions {
|
||||||
this.webBrowserFlags = const <String>[],
|
this.webBrowserFlags = const <String>[],
|
||||||
this.webLaunchUrl,
|
this.webLaunchUrl,
|
||||||
this.webHeaders = const <String, String>{},
|
this.webHeaders = const <String, String>{},
|
||||||
|
this.webRenderer = WebRendererMode.auto,
|
||||||
this.cacheSkSL = false,
|
this.cacheSkSL = false,
|
||||||
this.traceAllowlist,
|
this.traceAllowlist,
|
||||||
this.enableImpeller = ImpellerStatus.platformDefault,
|
this.enableImpeller = ImpellerStatus.platformDefault,
|
||||||
|
@ -1060,6 +1063,7 @@ class DebuggingOptions {
|
||||||
required this.webEnableExpressionEvaluation,
|
required this.webEnableExpressionEvaluation,
|
||||||
required this.webHeaders,
|
required this.webHeaders,
|
||||||
required this.webLaunchUrl,
|
required this.webLaunchUrl,
|
||||||
|
required this.webRenderer,
|
||||||
required this.vmserviceOutFile,
|
required this.vmserviceOutFile,
|
||||||
required this.fastStart,
|
required this.fastStart,
|
||||||
required this.nullAssertions,
|
required this.nullAssertions,
|
||||||
|
@ -1144,6 +1148,9 @@ class DebuggingOptions {
|
||||||
/// Allow developers to add custom headers to web server
|
/// Allow developers to add custom headers to web server
|
||||||
final Map<String, String> webHeaders;
|
final Map<String, String> 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.
|
/// A file where the VM Service URL should be written after the application is started.
|
||||||
final String? vmserviceOutFile;
|
final String? vmserviceOutFile;
|
||||||
final bool fastStart;
|
final bool fastStart;
|
||||||
|
@ -1252,6 +1259,7 @@ class DebuggingOptions {
|
||||||
'webEnableExpressionEvaluation': webEnableExpressionEvaluation,
|
'webEnableExpressionEvaluation': webEnableExpressionEvaluation,
|
||||||
'webLaunchUrl': webLaunchUrl,
|
'webLaunchUrl': webLaunchUrl,
|
||||||
'webHeaders': webHeaders,
|
'webHeaders': webHeaders,
|
||||||
|
'webRenderer': webRenderer.name,
|
||||||
'vmserviceOutFile': vmserviceOutFile,
|
'vmserviceOutFile': vmserviceOutFile,
|
||||||
'fastStart': fastStart,
|
'fastStart': fastStart,
|
||||||
'nullAssertions': nullAssertions,
|
'nullAssertions': nullAssertions,
|
||||||
|
@ -1307,6 +1315,7 @@ class DebuggingOptions {
|
||||||
webEnableExpressionEvaluation: json['webEnableExpressionEvaluation']! as bool,
|
webEnableExpressionEvaluation: json['webEnableExpressionEvaluation']! as bool,
|
||||||
webHeaders: (json['webHeaders']! as Map<dynamic, dynamic>).cast<String, String>(),
|
webHeaders: (json['webHeaders']! as Map<dynamic, dynamic>).cast<String, String>(),
|
||||||
webLaunchUrl: json['webLaunchUrl'] as String?,
|
webLaunchUrl: json['webLaunchUrl'] as String?,
|
||||||
|
webRenderer: WebRendererMode.values.byName(json['webRenderer']! as String),
|
||||||
vmserviceOutFile: json['vmserviceOutFile'] as String?,
|
vmserviceOutFile: json['vmserviceOutFile'] as String?,
|
||||||
fastStart: json['fastStart']! as bool,
|
fastStart: json['fastStart']! as bool,
|
||||||
nullAssertions: json['nullAssertions']! as bool,
|
nullAssertions: json['nullAssertions']! as bool,
|
||||||
|
|
|
@ -78,12 +78,14 @@ class WebDriverService extends DriverService {
|
||||||
buildInfo,
|
buildInfo,
|
||||||
port: debuggingOptions.port,
|
port: debuggingOptions.port,
|
||||||
hostname: debuggingOptions.hostname,
|
hostname: debuggingOptions.hostname,
|
||||||
|
webRenderer: debuggingOptions.webRenderer,
|
||||||
)
|
)
|
||||||
: DebuggingOptions.enabled(
|
: DebuggingOptions.enabled(
|
||||||
buildInfo,
|
buildInfo,
|
||||||
port: debuggingOptions.port,
|
port: debuggingOptions.port,
|
||||||
hostname: debuggingOptions.hostname,
|
hostname: debuggingOptions.hostname,
|
||||||
disablePortPublication: debuggingOptions.disablePortPublication,
|
disablePortPublication: debuggingOptions.disablePortPublication,
|
||||||
|
webRenderer: debuggingOptions.webRenderer,
|
||||||
),
|
),
|
||||||
stayResident: true,
|
stayResident: true,
|
||||||
flutterProject: FlutterProject.current(),
|
flutterProject: FlutterProject.current(),
|
||||||
|
|
|
@ -62,6 +62,7 @@ class IndexHtml {
|
||||||
void applySubstitutions({
|
void applySubstitutions({
|
||||||
required String baseHref,
|
required String baseHref,
|
||||||
required String? serviceWorkerVersion,
|
required String? serviceWorkerVersion,
|
||||||
|
String? buildConfig,
|
||||||
}) {
|
}) {
|
||||||
if (_content.contains(kBaseHrefPlaceholder)) {
|
if (_content.contains(kBaseHrefPlaceholder)) {
|
||||||
_content = _content.replaceAll(kBaseHrefPlaceholder, baseHref);
|
_content = _content.replaceAll(kBaseHrefPlaceholder, baseHref);
|
||||||
|
@ -81,6 +82,12 @@ class IndexHtml {
|
||||||
"navigator.serviceWorker.register('flutter_service_worker.js?v=$serviceWorkerVersion')",
|
"navigator.serviceWorker.register('flutter_service_worker.js?v=$serviceWorkerVersion')",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (buildConfig != null) {
|
||||||
|
_content = _content.replaceFirst(
|
||||||
|
'{{flutter_build_config}}',
|
||||||
|
buildConfig,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import '../build_system/targets/common.dart';
|
||||||
import '../build_system/targets/dart_plugin_registrant.dart';
|
import '../build_system/targets/dart_plugin_registrant.dart';
|
||||||
import '../build_system/targets/localizations.dart';
|
import '../build_system/targets/localizations.dart';
|
||||||
import '../build_system/targets/web.dart';
|
import '../build_system/targets/web.dart';
|
||||||
import '../web/compile.dart';
|
import '../web/compiler_config.dart';
|
||||||
|
|
||||||
class BuildTargetsImpl extends BuildTargets {
|
class BuildTargetsImpl extends BuildTargets {
|
||||||
const BuildTargetsImpl();
|
const BuildTargetsImpl();
|
||||||
|
@ -27,9 +27,6 @@ class BuildTargetsImpl extends BuildTargets {
|
||||||
Target get dartPluginRegistrantTarget => const DartPluginRegistrantTarget();
|
Target get dartPluginRegistrantTarget => const DartPluginRegistrantTarget();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Target webServiceWorker(
|
Target webServiceWorker(FileSystem fileSystem, List<WebCompilerConfig> compileConfigs) =>
|
||||||
FileSystem fileSystem, {
|
WebServiceWorker(fileSystem, compileConfigs);
|
||||||
required WebRendererMode webRenderer,
|
|
||||||
required bool isWasm,
|
|
||||||
}) => WebServiceWorker(fileSystem, webRenderer, isWasm: isWasm);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,8 +117,9 @@ class WebAssetServer implements AssetReader {
|
||||||
this.internetAddress,
|
this.internetAddress,
|
||||||
this._modules,
|
this._modules,
|
||||||
this._digests,
|
this._digests,
|
||||||
this._nullSafetyMode,
|
this._nullSafetyMode, {
|
||||||
) : basePath = _getIndexHtml().getBaseHref();
|
required this.webRenderer,
|
||||||
|
}) : basePath = _getIndexHtml().getBaseHref();
|
||||||
|
|
||||||
// Fallback to "application/octet-stream" on null which
|
// Fallback to "application/octet-stream" on null which
|
||||||
// makes no claims as to the structure of the data.
|
// makes no claims as to the structure of the data.
|
||||||
|
@ -177,6 +178,7 @@ class WebAssetServer implements AssetReader {
|
||||||
ExpressionCompiler? expressionCompiler,
|
ExpressionCompiler? expressionCompiler,
|
||||||
Map<String, String> extraHeaders,
|
Map<String, String> extraHeaders,
|
||||||
NullSafetyMode nullSafetyMode, {
|
NullSafetyMode nullSafetyMode, {
|
||||||
|
required WebRendererMode webRenderer,
|
||||||
bool testMode = false,
|
bool testMode = false,
|
||||||
DwdsLauncher dwdsLauncher = Dwds.start,
|
DwdsLauncher dwdsLauncher = Dwds.start,
|
||||||
}) async {
|
}) async {
|
||||||
|
@ -225,6 +227,7 @@ class WebAssetServer implements AssetReader {
|
||||||
modules,
|
modules,
|
||||||
digests,
|
digests,
|
||||||
nullSafetyMode,
|
nullSafetyMode,
|
||||||
|
webRenderer: webRenderer,
|
||||||
);
|
);
|
||||||
if (testMode) {
|
if (testMode) {
|
||||||
return server;
|
return server;
|
||||||
|
@ -504,16 +507,29 @@ class WebAssetServer implements AssetReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines what rendering backed to use.
|
/// Determines what rendering backed to use.
|
||||||
WebRendererMode webRenderer = WebRendererMode.html;
|
final WebRendererMode webRenderer;
|
||||||
|
|
||||||
shelf.Response _serveIndex() {
|
shelf.Response _serveIndex() {
|
||||||
|
|
||||||
final IndexHtml indexHtml = _getIndexHtml();
|
final IndexHtml indexHtml = _getIndexHtml();
|
||||||
|
|
||||||
|
final Map<String, dynamic> buildConfig = <String, dynamic>{
|
||||||
|
'engineRevision': globals.flutterVersion.engineRevision,
|
||||||
|
'builds': <dynamic>[
|
||||||
|
<String, dynamic>{
|
||||||
|
'compileTarget': 'dartdevc',
|
||||||
|
'renderer': webRenderer.name,
|
||||||
|
'mainJsPath': 'main.dart.js',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
final String buildConfigString = '_flutter.buildConfig = ${jsonEncode(buildConfig)};';
|
||||||
|
|
||||||
indexHtml.applySubstitutions(
|
indexHtml.applySubstitutions(
|
||||||
// Currently, we don't support --base-href for the "run" command.
|
// Currently, we don't support --base-href for the "run" command.
|
||||||
baseHref: '/',
|
baseHref: '/',
|
||||||
serviceWorkerVersion: null,
|
serviceWorkerVersion: null,
|
||||||
|
buildConfig: buildConfigString,
|
||||||
);
|
);
|
||||||
|
|
||||||
final Map<String, String> headers = <String, String>{
|
final Map<String, String> headers = <String, String>{
|
||||||
|
@ -663,6 +679,7 @@ class WebDevFS implements DevFS {
|
||||||
required this.nullAssertions,
|
required this.nullAssertions,
|
||||||
required this.nativeNullAssertions,
|
required this.nativeNullAssertions,
|
||||||
required this.nullSafetyMode,
|
required this.nullSafetyMode,
|
||||||
|
required this.webRenderer,
|
||||||
this.testMode = false,
|
this.testMode = false,
|
||||||
}) : _port = port;
|
}) : _port = port;
|
||||||
|
|
||||||
|
@ -686,6 +703,7 @@ class WebDevFS implements DevFS {
|
||||||
final NullSafetyMode nullSafetyMode;
|
final NullSafetyMode nullSafetyMode;
|
||||||
final String? tlsCertPath;
|
final String? tlsCertPath;
|
||||||
final String? tlsCertKeyPath;
|
final String? tlsCertKeyPath;
|
||||||
|
final WebRendererMode webRenderer;
|
||||||
|
|
||||||
late WebAssetServer webAssetServer;
|
late WebAssetServer webAssetServer;
|
||||||
|
|
||||||
|
@ -785,15 +803,11 @@ class WebDevFS implements DevFS {
|
||||||
expressionCompiler,
|
expressionCompiler,
|
||||||
extraHeaders,
|
extraHeaders,
|
||||||
nullSafetyMode,
|
nullSafetyMode,
|
||||||
|
webRenderer: webRenderer,
|
||||||
testMode: testMode,
|
testMode: testMode,
|
||||||
);
|
);
|
||||||
|
|
||||||
final int selectedPort = webAssetServer.selectedPort;
|
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';
|
String url = '$hostname:$selectedPort';
|
||||||
if (hostname == 'any') {
|
if (hostname == 'any') {
|
||||||
url ='localhost:$selectedPort';
|
url ='localhost:$selectedPort';
|
||||||
|
|
|
@ -309,6 +309,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
|
||||||
nullAssertions: debuggingOptions.nullAssertions,
|
nullAssertions: debuggingOptions.nullAssertions,
|
||||||
nullSafetyMode: debuggingOptions.buildInfo.nullSafetyMode,
|
nullSafetyMode: debuggingOptions.buildInfo.nullSafetyMode,
|
||||||
nativeNullAssertions: debuggingOptions.nativeNullAssertions,
|
nativeNullAssertions: debuggingOptions.nativeNullAssertions,
|
||||||
|
webRenderer: debuggingOptions.webRenderer,
|
||||||
);
|
);
|
||||||
Uri url = await device!.devFS!.create();
|
Uri url = await device!.devFS!.create();
|
||||||
if (debuggingOptions.tlsCertKeyPath != null && debuggingOptions.tlsCertPath != null) {
|
if (debuggingOptions.tlsCertKeyPath != null && debuggingOptions.tlsCertPath != null) {
|
||||||
|
@ -339,7 +340,12 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
|
||||||
target,
|
target,
|
||||||
debuggingOptions.buildInfo,
|
debuggingOptions.buildInfo,
|
||||||
ServiceWorkerStrategy.none,
|
ServiceWorkerStrategy.none,
|
||||||
compilerConfig: JsCompilerConfig.run(nativeNullAssertions: debuggingOptions.nativeNullAssertions)
|
compilerConfigs: <WebCompilerConfig>[
|
||||||
|
JsCompilerConfig.run(
|
||||||
|
nativeNullAssertions: debuggingOptions.nativeNullAssertions,
|
||||||
|
renderer: debuggingOptions.webRenderer,
|
||||||
|
)
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
await device!.device!.startApp(
|
await device!.device!.startApp(
|
||||||
|
@ -418,7 +424,12 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
|
||||||
target,
|
target,
|
||||||
debuggingOptions.buildInfo,
|
debuggingOptions.buildInfo,
|
||||||
ServiceWorkerStrategy.none,
|
ServiceWorkerStrategy.none,
|
||||||
compilerConfig: JsCompilerConfig.run(nativeNullAssertions: debuggingOptions.nativeNullAssertions),
|
compilerConfigs: <WebCompilerConfig>[
|
||||||
|
JsCompilerConfig.run(
|
||||||
|
nativeNullAssertions: debuggingOptions.nativeNullAssertions,
|
||||||
|
renderer: debuggingOptions.webRenderer,
|
||||||
|
)
|
||||||
|
],
|
||||||
);
|
);
|
||||||
} on ToolExit {
|
} on ToolExit {
|
||||||
return OperationResult(1, 'Failed to recompile application.');
|
return OperationResult(1, 'Failed to recompile application.');
|
||||||
|
|
|
@ -135,7 +135,7 @@ class FlutterDevice {
|
||||||
}
|
}
|
||||||
|
|
||||||
final String platformDillPath = globals.fs.path.join(
|
final String platformDillPath = globals.fs.path.join(
|
||||||
getWebPlatformBinariesDirectory(globals.artifacts!, buildInfo.webRenderer).path,
|
globals.artifacts!.getHostArtifact(HostArtifact.webPlatformKernelFolder).path,
|
||||||
platformDillName,
|
platformDillName,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1273,13 +1273,7 @@ abstract class FlutterCommand extends Command<void> {
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
final Map<String, Object?> defineConfigJsonMap = extractDartDefineConfigJsonMap();
|
final Map<String, Object?> defineConfigJsonMap = extractDartDefineConfigJsonMap();
|
||||||
List<String> dartDefines = extractDartDefines(defineConfigJsonMap: defineConfigJsonMap);
|
final List<String> 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)) {
|
if (argParser.options.containsKey(FlutterOptions.kWebResourcesCdnFlag)) {
|
||||||
final bool hasLocalWebSdk = argParser.options.containsKey('local-web-sdk') && stringArg('local-web-sdk') != null;
|
final bool hasLocalWebSdk = argParser.options.containsKey('local-web-sdk') && stringArg('local-web-sdk') != null;
|
||||||
|
@ -1327,7 +1321,6 @@ abstract class FlutterCommand extends Command<void> {
|
||||||
dartDefines: dartDefines,
|
dartDefines: dartDefines,
|
||||||
bundleSkSLPath: bundleSkSLPath,
|
bundleSkSLPath: bundleSkSLPath,
|
||||||
dartExperiments: experiments,
|
dartExperiments: experiments,
|
||||||
webRenderer: webRenderer,
|
|
||||||
performanceMeasurementFile: performanceMeasurementFile,
|
performanceMeasurementFile: performanceMeasurementFile,
|
||||||
packagesPath: packagesPath ?? globals.fs.path.absolute('.dart_tool', 'package_config.json'),
|
packagesPath: packagesPath ?? globals.fs.path.absolute('.dart_tool', 'package_config.json'),
|
||||||
nullSafetyMode: nullSafetyMode,
|
nullSafetyMode: nullSafetyMode,
|
||||||
|
@ -1566,19 +1559,6 @@ abstract class FlutterCommand extends Command<void> {
|
||||||
return jsonEncode(propertyMap);
|
return jsonEncode(propertyMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates dart-defines based on [webRenderer].
|
|
||||||
@visibleForTesting
|
|
||||||
static List<String> updateDartDefines(List<String> dartDefines, WebRendererMode webRenderer) {
|
|
||||||
final Set<String> 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<String, String> extractWebHeaders() {
|
Map<String, String> extractWebHeaders() {
|
||||||
final Map<String, String> webHeaders = <String, String>{};
|
final Map<String, String> webHeaders = <String, String>{};
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,12 @@ import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:async/async.dart';
|
import 'package:async/async.dart';
|
||||||
import 'package:http_multi_server/http_multi_server.dart';
|
import 'package:http_multi_server/http_multi_server.dart';
|
||||||
|
import 'package:mime/mime.dart' as mime;
|
||||||
import 'package:package_config/package_config.dart';
|
import 'package:package_config/package_config.dart';
|
||||||
import 'package:pool/pool.dart';
|
import 'package:pool/pool.dart';
|
||||||
import 'package:process/process.dart';
|
import 'package:process/process.dart';
|
||||||
import 'package:shelf/shelf.dart' as shelf;
|
import 'package:shelf/shelf.dart' as shelf;
|
||||||
import 'package:shelf/shelf_io.dart' as shelf_io;
|
import 'package:shelf/shelf_io.dart' as shelf_io;
|
||||||
import 'package:shelf_static/shelf_static.dart';
|
|
||||||
import 'package:shelf_web_socket/shelf_web_socket.dart';
|
import 'package:shelf_web_socket/shelf_web_socket.dart';
|
||||||
import 'package:stream_channel/stream_channel.dart';
|
import 'package:stream_channel/stream_channel.dart';
|
||||||
import 'package:test_core/src/platform.dart'; // ignore: implementation_imports
|
import 'package:test_core/src/platform.dart'; // ignore: implementation_imports
|
||||||
|
@ -37,6 +37,34 @@ import 'flutter_web_goldens.dart';
|
||||||
import 'test_compiler.dart';
|
import 'test_compiler.dart';
|
||||||
import 'test_time_recorder.dart';
|
import 'test_time_recorder.dart';
|
||||||
|
|
||||||
|
shelf.Handler createDirectoryHandler(Directory directory) {
|
||||||
|
final mime.MimeTypeResolver resolver = mime.MimeTypeResolver();
|
||||||
|
final FileSystem fileSystem = directory.fileSystem;
|
||||||
|
return (shelf.Request request) async {
|
||||||
|
String uriPath = request.requestedUri.path;
|
||||||
|
|
||||||
|
// Strip any leading slashes
|
||||||
|
if (uriPath.startsWith('/')) {
|
||||||
|
uriPath = uriPath.substring(1);
|
||||||
|
}
|
||||||
|
final String filePath = fileSystem.path.join(
|
||||||
|
directory.path,
|
||||||
|
uriPath,
|
||||||
|
);
|
||||||
|
final File file = fileSystem.file(filePath);
|
||||||
|
if (!file.existsSync()) {
|
||||||
|
return shelf.Response.notFound('Not Found');
|
||||||
|
}
|
||||||
|
final String? contentType = resolver.lookup(file.path);
|
||||||
|
return shelf.Response.ok(
|
||||||
|
file.openRead(),
|
||||||
|
headers: <String, String>{
|
||||||
|
if (contentType != null) 'Content-Type': contentType
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
class FlutterWebPlatform extends PlatformPlugin {
|
class FlutterWebPlatform extends PlatformPlugin {
|
||||||
FlutterWebPlatform._(this._server, this._config, this._root, {
|
FlutterWebPlatform._(this._server, this._config, this._root, {
|
||||||
FlutterProject? flutterProject,
|
FlutterProject? flutterProject,
|
||||||
|
@ -46,31 +74,32 @@ class FlutterWebPlatform extends PlatformPlugin {
|
||||||
required this.buildInfo,
|
required this.buildInfo,
|
||||||
required this.webMemoryFS,
|
required this.webMemoryFS,
|
||||||
required FileSystem fileSystem,
|
required FileSystem fileSystem,
|
||||||
required PackageConfig flutterToolPackageConfig,
|
required File testDartJs,
|
||||||
|
required File testHostDartJs,
|
||||||
required ChromiumLauncher chromiumLauncher,
|
required ChromiumLauncher chromiumLauncher,
|
||||||
required Logger logger,
|
required Logger logger,
|
||||||
required Artifacts? artifacts,
|
required Artifacts? artifacts,
|
||||||
required ProcessManager processManager,
|
required ProcessManager processManager,
|
||||||
|
required this.webRenderer,
|
||||||
TestTimeRecorder? testTimeRecorder,
|
TestTimeRecorder? testTimeRecorder,
|
||||||
}) : _fileSystem = fileSystem,
|
}) : _fileSystem = fileSystem,
|
||||||
_flutterToolPackageConfig = flutterToolPackageConfig,
|
_testDartJs = testDartJs,
|
||||||
|
_testHostDartJs = testHostDartJs,
|
||||||
_chromiumLauncher = chromiumLauncher,
|
_chromiumLauncher = chromiumLauncher,
|
||||||
_logger = logger,
|
_logger = logger,
|
||||||
_artifacts = artifacts {
|
_artifacts = artifacts {
|
||||||
final shelf.Cascade cascade = shelf.Cascade()
|
final shelf.Cascade cascade = shelf.Cascade()
|
||||||
.add(_webSocketHandler.handler)
|
.add(_webSocketHandler.handler)
|
||||||
.add(createStaticHandler(
|
.add(createDirectoryHandler(
|
||||||
fileSystem.path.join(Cache.flutterRoot!, 'packages', 'flutter_tools'),
|
fileSystem.directory(fileSystem.path.join(Cache.flutterRoot!, 'packages', 'flutter_tools')),
|
||||||
serveFilesOutsidePath: true,
|
|
||||||
))
|
))
|
||||||
.add(_handleStaticArtifact)
|
.add(_handleStaticArtifact)
|
||||||
.add(_localCanvasKitHandler)
|
.add(_localCanvasKitHandler)
|
||||||
.add(_goldenFileHandler)
|
.add(_goldenFileHandler)
|
||||||
.add(_wrapperHandler)
|
.add(_wrapperHandler)
|
||||||
.add(_handleTestRequest)
|
.add(_handleTestRequest)
|
||||||
.add(createStaticHandler(
|
.add(createDirectoryHandler(
|
||||||
fileSystem.path.join(fileSystem.currentDirectory.path, 'test'),
|
fileSystem.directory(fileSystem.path.join(fileSystem.currentDirectory.path, 'test'))
|
||||||
serveFilesOutsidePath: true,
|
|
||||||
))
|
))
|
||||||
.add(_packageFilesHandler);
|
.add(_packageFilesHandler);
|
||||||
_server.mount(cascade.handler);
|
_server.mount(cascade.handler);
|
||||||
|
@ -80,14 +109,15 @@ class FlutterWebPlatform extends PlatformPlugin {
|
||||||
fileSystem: _fileSystem,
|
fileSystem: _fileSystem,
|
||||||
logger: _logger,
|
logger: _logger,
|
||||||
processManager: processManager,
|
processManager: processManager,
|
||||||
webRenderer: _rendererMode,
|
webRenderer: webRenderer,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final WebMemoryFS webMemoryFS;
|
final WebMemoryFS webMemoryFS;
|
||||||
final BuildInfo buildInfo;
|
final BuildInfo buildInfo;
|
||||||
final FileSystem _fileSystem;
|
final FileSystem _fileSystem;
|
||||||
final PackageConfig _flutterToolPackageConfig;
|
final File _testDartJs;
|
||||||
|
final File _testHostDartJs;
|
||||||
final ChromiumLauncher _chromiumLauncher;
|
final ChromiumLauncher _chromiumLauncher;
|
||||||
final Logger _logger;
|
final Logger _logger;
|
||||||
final Artifacts? _artifacts;
|
final Artifacts? _artifacts;
|
||||||
|
@ -96,6 +126,7 @@ class FlutterWebPlatform extends PlatformPlugin {
|
||||||
final OneOffHandler _webSocketHandler = OneOffHandler();
|
final OneOffHandler _webSocketHandler = OneOffHandler();
|
||||||
final AsyncMemoizer<void> _closeMemo = AsyncMemoizer<void>();
|
final AsyncMemoizer<void> _closeMemo = AsyncMemoizer<void>();
|
||||||
final String _root;
|
final String _root;
|
||||||
|
final WebRendererMode webRenderer;
|
||||||
|
|
||||||
/// Allows only one test suite (typically one test file) to be loaded and run
|
/// Allows only one test suite (typically one test file) to be loaded and run
|
||||||
/// at any given point in time. Loading more than one file at a time is known
|
/// at any given point in time. Loading more than one file at a time is known
|
||||||
|
@ -105,6 +136,10 @@ class FlutterWebPlatform extends PlatformPlugin {
|
||||||
BrowserManager? _browserManager;
|
BrowserManager? _browserManager;
|
||||||
late TestGoldenComparator _testGoldenComparator;
|
late TestGoldenComparator _testGoldenComparator;
|
||||||
|
|
||||||
|
static Future<shelf.Server> defaultServerFactory() async {
|
||||||
|
return shelf_io.IOServer(await HttpMultiServer.loopback(0));
|
||||||
|
}
|
||||||
|
|
||||||
static Future<FlutterWebPlatform> start(String root, {
|
static Future<FlutterWebPlatform> start(String root, {
|
||||||
FlutterProject? flutterProject,
|
FlutterProject? flutterProject,
|
||||||
String? shellPath,
|
String? shellPath,
|
||||||
|
@ -118,19 +153,37 @@ class FlutterWebPlatform extends PlatformPlugin {
|
||||||
required ChromiumLauncher chromiumLauncher,
|
required ChromiumLauncher chromiumLauncher,
|
||||||
required Artifacts? artifacts,
|
required Artifacts? artifacts,
|
||||||
required ProcessManager processManager,
|
required ProcessManager processManager,
|
||||||
|
required WebRendererMode webRenderer,
|
||||||
TestTimeRecorder? testTimeRecorder,
|
TestTimeRecorder? testTimeRecorder,
|
||||||
|
Uri? testPackageUri,
|
||||||
|
Future<shelf.Server> Function() serverFactory = defaultServerFactory,
|
||||||
}) async {
|
}) async {
|
||||||
final shelf_io.IOServer server = shelf_io.IOServer(await HttpMultiServer.loopback(0));
|
final shelf.Server server = await serverFactory();
|
||||||
final PackageConfig packageConfig = await loadPackageConfigWithLogging(
|
if (testPackageUri == null) {
|
||||||
fileSystem.file(fileSystem.path.join(
|
final PackageConfig packageConfig = await loadPackageConfigWithLogging(
|
||||||
Cache.flutterRoot!,
|
fileSystem.file(fileSystem.path.join(
|
||||||
'packages',
|
Cache.flutterRoot!,
|
||||||
'flutter_tools',
|
'packages',
|
||||||
'.dart_tool',
|
'flutter_tools',
|
||||||
'package_config.json',
|
'.dart_tool',
|
||||||
)),
|
'package_config.json',
|
||||||
logger: logger,
|
)),
|
||||||
);
|
logger: logger,
|
||||||
|
);
|
||||||
|
testPackageUri = packageConfig['test']!.packageUriRoot;
|
||||||
|
}
|
||||||
|
final File testDartJs = fileSystem.file(fileSystem.path.join(
|
||||||
|
testPackageUri.toFilePath(),
|
||||||
|
'dart.js',
|
||||||
|
));
|
||||||
|
final File testHostDartJs = fileSystem.file(fileSystem.path.join(
|
||||||
|
testPackageUri.toFilePath(),
|
||||||
|
'src',
|
||||||
|
'runner',
|
||||||
|
'browser',
|
||||||
|
'static',
|
||||||
|
'host.dart.js',
|
||||||
|
));
|
||||||
return FlutterWebPlatform._(
|
return FlutterWebPlatform._(
|
||||||
server,
|
server,
|
||||||
Configuration.current.change(pauseAfterLoad: pauseAfterLoad),
|
Configuration.current.change(pauseAfterLoad: pauseAfterLoad),
|
||||||
|
@ -140,28 +193,21 @@ class FlutterWebPlatform extends PlatformPlugin {
|
||||||
updateGoldens: updateGoldens,
|
updateGoldens: updateGoldens,
|
||||||
buildInfo: buildInfo,
|
buildInfo: buildInfo,
|
||||||
webMemoryFS: webMemoryFS,
|
webMemoryFS: webMemoryFS,
|
||||||
flutterToolPackageConfig: packageConfig,
|
testDartJs: testDartJs,
|
||||||
|
testHostDartJs: testHostDartJs,
|
||||||
fileSystem: fileSystem,
|
fileSystem: fileSystem,
|
||||||
chromiumLauncher: chromiumLauncher,
|
chromiumLauncher: chromiumLauncher,
|
||||||
artifacts: artifacts,
|
artifacts: artifacts,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
nullAssertions: nullAssertions,
|
nullAssertions: nullAssertions,
|
||||||
processManager: processManager,
|
processManager: processManager,
|
||||||
|
webRenderer: webRenderer,
|
||||||
testTimeRecorder: testTimeRecorder,
|
testTimeRecorder: testTimeRecorder,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get _closed => _closeMemo.hasRun;
|
bool get _closed => _closeMemo.hasRun;
|
||||||
|
|
||||||
/// Uri of the test package.
|
|
||||||
Uri get testUri => _flutterToolPackageConfig['test']!.packageUriRoot;
|
|
||||||
|
|
||||||
WebRendererMode get _rendererMode {
|
|
||||||
return buildInfo.dartDefines.contains('FLUTTER_WEB_USE_SKIA=true')
|
|
||||||
? WebRendererMode.canvaskit
|
|
||||||
: WebRendererMode.html;
|
|
||||||
}
|
|
||||||
|
|
||||||
NullSafetyMode get _nullSafetyMode {
|
NullSafetyMode get _nullSafetyMode {
|
||||||
return buildInfo.nullSafetyMode == NullSafetyMode.sound
|
return buildInfo.nullSafetyMode == NullSafetyMode.sound
|
||||||
? NullSafetyMode.sound
|
? NullSafetyMode.sound
|
||||||
|
@ -200,25 +246,10 @@ class FlutterWebPlatform extends PlatformPlugin {
|
||||||
));
|
));
|
||||||
|
|
||||||
File get _dartSdk => _fileSystem.file(
|
File get _dartSdk => _fileSystem.file(
|
||||||
_artifacts!.getHostArtifact(kDartSdkJsArtifactMap[_rendererMode]![_nullSafetyMode]!));
|
_artifacts!.getHostArtifact(kDartSdkJsArtifactMap[webRenderer]![_nullSafetyMode]!));
|
||||||
|
|
||||||
File get _dartSdkSourcemaps => _fileSystem.file(
|
File get _dartSdkSourcemaps => _fileSystem.file(
|
||||||
_artifacts!.getHostArtifact(kDartSdkJsMapArtifactMap[_rendererMode]![_nullSafetyMode]!));
|
_artifacts!.getHostArtifact(kDartSdkJsMapArtifactMap[webRenderer]![_nullSafetyMode]!));
|
||||||
|
|
||||||
/// The precompiled test javascript.
|
|
||||||
File get _testDartJs => _fileSystem.file(_fileSystem.path.join(
|
|
||||||
testUri.toFilePath(),
|
|
||||||
'dart.js',
|
|
||||||
));
|
|
||||||
|
|
||||||
File get _testHostDartJs => _fileSystem.file(_fileSystem.path.join(
|
|
||||||
testUri.toFilePath(),
|
|
||||||
'src',
|
|
||||||
'runner',
|
|
||||||
'browser',
|
|
||||||
'static',
|
|
||||||
'host.dart.js',
|
|
||||||
));
|
|
||||||
|
|
||||||
File _canvasKitFile(String relativePath) {
|
File _canvasKitFile(String relativePath) {
|
||||||
final String canvasKitPath = _fileSystem.path.join(
|
final String canvasKitPath = _fileSystem.path.join(
|
||||||
|
@ -314,7 +345,7 @@ class FlutterWebPlatform extends PlatformPlugin {
|
||||||
if (fileUri != null) {
|
if (fileUri != null) {
|
||||||
final String dirname = _fileSystem.path.dirname(fileUri.toFilePath());
|
final String dirname = _fileSystem.path.dirname(fileUri.toFilePath());
|
||||||
final String basename = _fileSystem.path.basename(fileUri.toFilePath());
|
final String basename = _fileSystem.path.basename(fileUri.toFilePath());
|
||||||
final shelf.Handler handler = createStaticHandler(dirname);
|
final shelf.Handler handler = createDirectoryHandler(_fileSystem.directory(dirname));
|
||||||
final shelf.Request modifiedRequest = shelf.Request(
|
final shelf.Request modifiedRequest = shelf.Request(
|
||||||
request.method,
|
request.method,
|
||||||
request.requestedUri.replace(path: basename),
|
request.requestedUri.replace(path: basename),
|
||||||
|
|
|
@ -151,6 +151,7 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner {
|
||||||
testOutputDir: tempBuildDir,
|
testOutputDir: tempBuildDir,
|
||||||
testFiles: testFiles.map((Uri uri) => uri.toFilePath()).toList(),
|
testFiles: testFiles.map((Uri uri) => uri.toFilePath()).toList(),
|
||||||
buildInfo: debuggingOptions.buildInfo,
|
buildInfo: debuggingOptions.buildInfo,
|
||||||
|
webRenderer: debuggingOptions.webRenderer,
|
||||||
);
|
);
|
||||||
testArgs
|
testArgs
|
||||||
..add('--platform=chrome')
|
..add('--platform=chrome')
|
||||||
|
@ -181,6 +182,7 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner {
|
||||||
logger: globals.logger,
|
logger: globals.logger,
|
||||||
),
|
),
|
||||||
testTimeRecorder: testTimeRecorder,
|
testTimeRecorder: testTimeRecorder,
|
||||||
|
webRenderer: debuggingOptions.webRenderer,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -17,6 +17,7 @@ import '../cache.dart';
|
||||||
import '../compile.dart';
|
import '../compile.dart';
|
||||||
import '../dart/language_version.dart';
|
import '../dart/language_version.dart';
|
||||||
import '../web/bootstrap.dart';
|
import '../web/bootstrap.dart';
|
||||||
|
import '../web/compile.dart';
|
||||||
import '../web/memory_fs.dart';
|
import '../web/memory_fs.dart';
|
||||||
import 'test_config.dart';
|
import 'test_config.dart';
|
||||||
|
|
||||||
|
@ -48,6 +49,7 @@ class WebTestCompiler {
|
||||||
required String testOutputDir,
|
required String testOutputDir,
|
||||||
required List<String> testFiles,
|
required List<String> testFiles,
|
||||||
required BuildInfo buildInfo,
|
required BuildInfo buildInfo,
|
||||||
|
required WebRendererMode webRenderer,
|
||||||
}) async {
|
}) async {
|
||||||
LanguageVersion languageVersion = LanguageVersion(2, 8);
|
LanguageVersion languageVersion = LanguageVersion(2, 8);
|
||||||
late final String platformDillName;
|
late final String platformDillName;
|
||||||
|
@ -69,7 +71,7 @@ class WebTestCompiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
final String platformDillPath = _fileSystem.path.join(
|
final String platformDillPath = _fileSystem.path.join(
|
||||||
getWebPlatformBinariesDirectory(_artifacts, buildInfo.webRenderer).path,
|
_artifacts.getHostArtifact(HostArtifact.webPlatformKernelFolder).path,
|
||||||
platformDillName
|
platformDillName
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -109,6 +111,7 @@ class WebTestCompiler {
|
||||||
fileSystem: _fileSystem,
|
fileSystem: _fileSystem,
|
||||||
config: _config,
|
config: _config,
|
||||||
);
|
);
|
||||||
|
final List<String> dartDefines = webRenderer.updateDartDefines(buildInfo.dartDefines);
|
||||||
final ResidentCompiler residentCompiler = ResidentCompiler(
|
final ResidentCompiler residentCompiler = ResidentCompiler(
|
||||||
_artifacts.getHostArtifact(HostArtifact.flutterWebSdk).path,
|
_artifacts.getHostArtifact(HostArtifact.flutterWebSdk).path,
|
||||||
buildMode: buildInfo.mode,
|
buildMode: buildInfo.mode,
|
||||||
|
@ -124,7 +127,7 @@ class WebTestCompiler {
|
||||||
targetModel: TargetModel.dartdevc,
|
targetModel: TargetModel.dartdevc,
|
||||||
extraFrontEndOptions: extraFrontEndOptions,
|
extraFrontEndOptions: extraFrontEndOptions,
|
||||||
platformDill: _fileSystem.file(platformDillPath).absolute.uri.toString(),
|
platformDill: _fileSystem.file(platformDillPath).absolute.uri.toString(),
|
||||||
dartDefines: buildInfo.dartDefines,
|
dartDefines: dartDefines,
|
||||||
librariesSpec: _artifacts.getHostArtifact(HostArtifact.flutterWebLibrariesJson).uri.toString(),
|
librariesSpec: _artifacts.getHostArtifact(HostArtifact.flutterWebLibrariesJson).uri.toString(),
|
||||||
packagesPath: buildInfo.packagesPath,
|
packagesPath: buildInfo.packagesPath,
|
||||||
artifacts: _artifacts,
|
artifacts: _artifacts,
|
||||||
|
|
|
@ -24,7 +24,6 @@ import '../version.dart';
|
||||||
import 'compiler_config.dart';
|
import 'compiler_config.dart';
|
||||||
import 'file_generators/flutter_service_worker_js.dart';
|
import 'file_generators/flutter_service_worker_js.dart';
|
||||||
import 'migrations/scrub_generated_plugin_registrant.dart';
|
import 'migrations/scrub_generated_plugin_registrant.dart';
|
||||||
import 'web_constants.dart';
|
|
||||||
|
|
||||||
export 'compiler_config.dart';
|
export 'compiler_config.dart';
|
||||||
|
|
||||||
|
@ -67,23 +66,14 @@ class WebBuilder {
|
||||||
String target,
|
String target,
|
||||||
BuildInfo buildInfo,
|
BuildInfo buildInfo,
|
||||||
ServiceWorkerStrategy serviceWorkerStrategy, {
|
ServiceWorkerStrategy serviceWorkerStrategy, {
|
||||||
required WebCompilerConfig compilerConfig,
|
required List<WebCompilerConfig> compilerConfigs,
|
||||||
String? baseHref,
|
String? baseHref,
|
||||||
String? outputDirectoryPath,
|
String? outputDirectoryPath,
|
||||||
}) async {
|
}) async {
|
||||||
if (compilerConfig.isWasm) {
|
|
||||||
globals.logger.printBox(
|
|
||||||
title: 'Experimental feature',
|
|
||||||
'''
|
|
||||||
WebAssembly compilation is experimental.
|
|
||||||
$kWasmMoreInfo''',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final bool hasWebPlugins =
|
final bool hasWebPlugins =
|
||||||
(await findPlugins(flutterProject)).any((Plugin p) => p.platforms.containsKey(WebPlugin.kConfigKey));
|
(await findPlugins(flutterProject)).any((Plugin p) => p.platforms.containsKey(WebPlugin.kConfigKey));
|
||||||
final Directory outputDirectory = outputDirectoryPath == null
|
final Directory outputDirectory = outputDirectoryPath == null
|
||||||
? _fileSystem.directory(getWebBuildDirectory(compilerConfig.isWasm))
|
? _fileSystem.directory(getWebBuildDirectory())
|
||||||
: _fileSystem.directory(outputDirectoryPath);
|
: _fileSystem.directory(outputDirectoryPath);
|
||||||
outputDirectory.createSync(recursive: true);
|
outputDirectory.createSync(recursive: true);
|
||||||
|
|
||||||
|
@ -99,11 +89,7 @@ class WebBuilder {
|
||||||
final Stopwatch sw = Stopwatch()..start();
|
final Stopwatch sw = Stopwatch()..start();
|
||||||
try {
|
try {
|
||||||
final BuildResult result = await _buildSystem.build(
|
final BuildResult result = await _buildSystem.build(
|
||||||
globals.buildTargets.webServiceWorker(
|
globals.buildTargets.webServiceWorker(_fileSystem, compilerConfigs),
|
||||||
_fileSystem,
|
|
||||||
webRenderer: buildInfo.webRenderer,
|
|
||||||
isWasm: compilerConfig.isWasm,
|
|
||||||
),
|
|
||||||
Environment(
|
Environment(
|
||||||
projectDir: _fileSystem.currentDirectory,
|
projectDir: _fileSystem.currentDirectory,
|
||||||
outputDir: outputDirectory,
|
outputDir: outputDirectory,
|
||||||
|
@ -113,7 +99,6 @@ class WebBuilder {
|
||||||
kHasWebPlugins: hasWebPlugins.toString(),
|
kHasWebPlugins: hasWebPlugins.toString(),
|
||||||
if (baseHref != null) kBaseHref: baseHref,
|
if (baseHref != null) kBaseHref: baseHref,
|
||||||
kServiceWorkerStrategy: serviceWorkerStrategy.cliName,
|
kServiceWorkerStrategy: serviceWorkerStrategy.cliName,
|
||||||
...compilerConfig.toBuildSystemEnvironment(),
|
|
||||||
...buildInfo.toBuildSystemEnvironment(),
|
...buildInfo.toBuildSystemEnvironment(),
|
||||||
},
|
},
|
||||||
artifacts: globals.artifacts!,
|
artifacts: globals.artifacts!,
|
||||||
|
@ -146,8 +131,7 @@ class WebBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
final String buildSettingsString = _buildEventAnalyticsSettings(
|
final String buildSettingsString = _buildEventAnalyticsSettings(
|
||||||
config: compilerConfig,
|
configs: compilerConfigs,
|
||||||
buildInfo: buildInfo,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
BuildEvent(
|
BuildEvent(
|
||||||
|
@ -163,14 +147,15 @@ class WebBuilder {
|
||||||
));
|
));
|
||||||
|
|
||||||
final Duration elapsedDuration = sw.elapsed;
|
final Duration elapsedDuration = sw.elapsed;
|
||||||
|
final String variableName = compilerConfigs.length > 1 ? 'dual-compile' : 'dart2js';
|
||||||
_flutterUsage.sendTiming(
|
_flutterUsage.sendTiming(
|
||||||
'build',
|
'build',
|
||||||
compilerConfig.isWasm ? 'dart2wasm' : 'dart2js',
|
variableName,
|
||||||
elapsedDuration,
|
elapsedDuration,
|
||||||
);
|
);
|
||||||
_analytics.send(Event.timing(
|
_analytics.send(Event.timing(
|
||||||
workflow: 'build',
|
workflow: 'build',
|
||||||
variableName: compilerConfig.isWasm ? 'dart2wasm' : 'dart2js',
|
variableName: variableName,
|
||||||
elapsedMilliseconds: elapsedDuration.inMilliseconds,
|
elapsedMilliseconds: elapsedDuration.inMilliseconds,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -222,6 +207,16 @@ enum WebRendererMode implements CliEnum {
|
||||||
'FLUTTER_WEB_USE_SKWASM=true',
|
'FLUTTER_WEB_USE_SKWASM=true',
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
List<String> updateDartDefines(List<String> inputDefines) {
|
||||||
|
final Set<String> dartDefinesSet = inputDefines.toSet();
|
||||||
|
if (!inputDefines.any((String d) => d.startsWith('FLUTTER_WEB_AUTO_DETECT='))
|
||||||
|
&& inputDefines.any((String d) => d.startsWith('FLUTTER_WEB_USE_SKIA='))) {
|
||||||
|
dartDefinesSet.removeWhere((String d) => d.startsWith('FLUTTER_WEB_USE_SKIA='));
|
||||||
|
}
|
||||||
|
dartDefinesSet.addAll(dartDefines);
|
||||||
|
return dartDefinesSet.toList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The correct precompiled artifact to use for each build and render mode.
|
/// The correct precompiled artifact to use for each build and render mode.
|
||||||
|
@ -257,13 +252,18 @@ const Map<WebRendererMode, Map<NullSafetyMode, HostArtifact>> kDartSdkJsMapArtif
|
||||||
};
|
};
|
||||||
|
|
||||||
String _buildEventAnalyticsSettings({
|
String _buildEventAnalyticsSettings({
|
||||||
required WebCompilerConfig config,
|
required List<WebCompilerConfig> configs,
|
||||||
required BuildInfo buildInfo,
|
|
||||||
}) {
|
}) {
|
||||||
final Map<String, Object> values = <String, Object>{
|
final Map<String, Object> values = <String, Object>{};
|
||||||
...config.buildEventAnalyticsValues,
|
final List<String> renderers = <String>[];
|
||||||
'web-renderer': buildInfo.webRenderer.cliName,
|
final List<String> targets = <String>[];
|
||||||
};
|
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 List<String> sortedList = values.entries
|
final List<String> sortedList = values.entries
|
||||||
.map((MapEntry<String, Object> e) => '${e.key}: ${e.value};')
|
.map((MapEntry<String, Object> e) => '${e.key}: ${e.value};')
|
||||||
|
|
|
@ -3,58 +3,48 @@
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import '../base/utils.dart';
|
import '../base/utils.dart';
|
||||||
|
import '../convert.dart';
|
||||||
|
import 'compile.dart';
|
||||||
|
|
||||||
abstract class WebCompilerConfig {
|
enum CompileTarget {
|
||||||
const WebCompilerConfig();
|
js,
|
||||||
|
wasm,
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if `this` represents configuration for the Wasm compiler.
|
sealed class WebCompilerConfig {
|
||||||
///
|
const WebCompilerConfig({required this.renderer});
|
||||||
/// Otherwise, `false`–represents the JavaScript compiler.
|
|
||||||
bool get isWasm;
|
|
||||||
|
|
||||||
Map<String, String> toBuildSystemEnvironment();
|
/// Returns which target this compiler outputs (js or wasm)
|
||||||
|
CompileTarget get compileTarget;
|
||||||
|
final WebRendererMode renderer;
|
||||||
|
|
||||||
Map<String, Object> get buildEventAnalyticsValues => <String, Object>{
|
String get buildKey;
|
||||||
'wasm-compile': isWasm,
|
|
||||||
};
|
Map<String, Object> get buildEventAnalyticsValues => <String, Object>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configuration for the Dart-to-Javascript compiler (dart2js).
|
/// Configuration for the Dart-to-Javascript compiler (dart2js).
|
||||||
class JsCompilerConfig extends WebCompilerConfig {
|
class JsCompilerConfig extends WebCompilerConfig {
|
||||||
const JsCompilerConfig({
|
const JsCompilerConfig({
|
||||||
required this.csp,
|
this.csp = false,
|
||||||
required this.dumpInfo,
|
this.dumpInfo = false,
|
||||||
required this.nativeNullAssertions,
|
this.nativeNullAssertions = false,
|
||||||
required this.optimizationLevel,
|
this.optimizationLevel = kDart2jsDefaultOptimizationLevel,
|
||||||
required this.noFrequencyBasedMinification,
|
this.noFrequencyBasedMinification = false,
|
||||||
required this.sourceMaps,
|
this.sourceMaps = true,
|
||||||
|
super.renderer = WebRendererMode.auto,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Instantiates [JsCompilerConfig] suitable for the `flutter run` command.
|
/// Instantiates [JsCompilerConfig] suitable for the `flutter run` command.
|
||||||
const JsCompilerConfig.run({required bool nativeNullAssertions})
|
const JsCompilerConfig.run({
|
||||||
: this(
|
required bool nativeNullAssertions,
|
||||||
csp: false,
|
required WebRendererMode renderer,
|
||||||
dumpInfo: false,
|
}) : this(
|
||||||
nativeNullAssertions: nativeNullAssertions,
|
nativeNullAssertions: nativeNullAssertions,
|
||||||
noFrequencyBasedMinification: false,
|
|
||||||
optimizationLevel: kDart2jsDefaultOptimizationLevel,
|
optimizationLevel: kDart2jsDefaultOptimizationLevel,
|
||||||
sourceMaps: true,
|
renderer: renderer,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Creates a new [JsCompilerConfig] from build system environment values.
|
|
||||||
///
|
|
||||||
/// Should correspond exactly with [toBuildSystemEnvironment].
|
|
||||||
factory JsCompilerConfig.fromBuildSystemEnvironment(
|
|
||||||
Map<String, String> 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.
|
/// The default optimization level for dart2js.
|
||||||
///
|
///
|
||||||
/// Maps to [kDart2jsOptimization].
|
/// Maps to [kDart2jsOptimization].
|
||||||
|
@ -102,17 +92,7 @@ class JsCompilerConfig extends WebCompilerConfig {
|
||||||
final bool sourceMaps;
|
final bool sourceMaps;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool get isWasm => false;
|
CompileTarget get compileTarget => CompileTarget.js;
|
||||||
|
|
||||||
@override
|
|
||||||
Map<String, String> toBuildSystemEnvironment() => <String, String>{
|
|
||||||
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.
|
/// Arguments to use in both phases: full JS compile and CFE-only.
|
||||||
List<String> toSharedCommandOptions() => <String>[
|
List<String> toSharedCommandOptions() => <String>[
|
||||||
|
@ -130,25 +110,29 @@ class JsCompilerConfig extends WebCompilerConfig {
|
||||||
if (noFrequencyBasedMinification) '--no-frequency-based-minification',
|
if (noFrequencyBasedMinification) '--no-frequency-based-minification',
|
||||||
if (csp) '--csp',
|
if (csp) '--csp',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get buildKey {
|
||||||
|
final Map<String, dynamic> settings = <String, dynamic>{
|
||||||
|
'csp': csp,
|
||||||
|
'dumpInfo': dumpInfo,
|
||||||
|
'nativeNullAssertions': nativeNullAssertions,
|
||||||
|
'noFrequencyBasedMinification': noFrequencyBasedMinification,
|
||||||
|
'optimizationLevel': optimizationLevel,
|
||||||
|
'sourceMaps': sourceMaps,
|
||||||
|
};
|
||||||
|
return jsonEncode(settings);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configuration for the Wasm compiler.
|
/// Configuration for the Wasm compiler.
|
||||||
class WasmCompilerConfig extends WebCompilerConfig {
|
class WasmCompilerConfig extends WebCompilerConfig {
|
||||||
const WasmCompilerConfig({
|
const WasmCompilerConfig({
|
||||||
required this.omitTypeChecks,
|
this.omitTypeChecks = false,
|
||||||
required this.wasmOpt,
|
this.wasmOpt = WasmOptLevel.defaultValue,
|
||||||
|
super.renderer = WebRendererMode.auto,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Creates a new [WasmCompilerConfig] from build system environment values.
|
|
||||||
///
|
|
||||||
/// Should correspond exactly with [toBuildSystemEnvironment].
|
|
||||||
factory WasmCompilerConfig.fromBuildSystemEnvironment(
|
|
||||||
Map<String, String> defines) =>
|
|
||||||
WasmCompilerConfig(
|
|
||||||
omitTypeChecks: defines[kOmitTypeChecks] == 'true',
|
|
||||||
wasmOpt: WasmOptLevel.values.byName(defines[kRunWasmOpt]!),
|
|
||||||
);
|
|
||||||
|
|
||||||
/// Build environment for [omitTypeChecks].
|
/// Build environment for [omitTypeChecks].
|
||||||
static const String kOmitTypeChecks = 'WasmOmitTypeChecks';
|
static const String kOmitTypeChecks = 'WasmOmitTypeChecks';
|
||||||
|
|
||||||
|
@ -162,25 +146,31 @@ class WasmCompilerConfig extends WebCompilerConfig {
|
||||||
final WasmOptLevel wasmOpt;
|
final WasmOptLevel wasmOpt;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool get isWasm => true;
|
CompileTarget get compileTarget => CompileTarget.wasm;
|
||||||
|
|
||||||
bool get runWasmOpt => wasmOpt == WasmOptLevel.full || wasmOpt == WasmOptLevel.debug;
|
bool get runWasmOpt =>
|
||||||
|
wasmOpt == WasmOptLevel.full || wasmOpt == WasmOptLevel.debug;
|
||||||
@override
|
|
||||||
Map<String, String> toBuildSystemEnvironment() => <String, String>{
|
|
||||||
kOmitTypeChecks: omitTypeChecks.toString(),
|
|
||||||
kRunWasmOpt: wasmOpt.name,
|
|
||||||
};
|
|
||||||
|
|
||||||
List<String> toCommandOptions() => <String>[
|
List<String> toCommandOptions() => <String>[
|
||||||
if (omitTypeChecks) '--omit-type-checks',
|
if (omitTypeChecks) '--omit-type-checks',
|
||||||
];
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map<String, Object> get buildEventAnalyticsValues => <String, Object>{
|
Map<String, Object> get buildEventAnalyticsValues => <String, Object>{
|
||||||
...super.buildEventAnalyticsValues,
|
...super.buildEventAnalyticsValues,
|
||||||
...toBuildSystemEnvironment(),
|
kOmitTypeChecks: omitTypeChecks.toString(),
|
||||||
};
|
kRunWasmOpt: wasmOpt.name,
|
||||||
|
};
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get buildKey {
|
||||||
|
final Map<String, dynamic> settings = <String, dynamic>{
|
||||||
|
'omitTypeChecks': omitTypeChecks,
|
||||||
|
'wasmOpt': wasmOpt.name,
|
||||||
|
};
|
||||||
|
return jsonEncode(settings);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum WasmOptLevel implements CliEnum {
|
enum WasmOptLevel implements CliEnum {
|
||||||
|
@ -195,8 +185,11 @@ enum WasmOptLevel implements CliEnum {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get helpText => switch (this) {
|
String get helpText => switch (this) {
|
||||||
WasmOptLevel.none => 'wasm-opt is not run. Fastest build; bigger, slower output.',
|
WasmOptLevel.none =>
|
||||||
WasmOptLevel.debug => 'Similar to `${WasmOptLevel.full.name}`, but member names are preserved. Debugging is easier, but size is a bit bigger.',
|
'wasm-opt is not run. Fastest build; bigger, slower output.',
|
||||||
WasmOptLevel.full => 'wasm-opt is run. Build time is slower, but output is smaller and faster.',
|
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.',
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,13 @@ import 'package:flutter_tools/src/base/platform.dart';
|
||||||
import 'package:flutter_tools/src/base/process.dart';
|
import 'package:flutter_tools/src/base/process.dart';
|
||||||
import 'package:flutter_tools/src/build_info.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/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/cache.dart';
|
||||||
import 'package:flutter_tools/src/commands/build.dart';
|
import 'package:flutter_tools/src/commands/build.dart';
|
||||||
import 'package:flutter_tools/src/commands/build_web.dart';
|
import 'package:flutter_tools/src/commands/build_web.dart';
|
||||||
import 'package:flutter_tools/src/features.dart';
|
import 'package:flutter_tools/src/features.dart';
|
||||||
import 'package:flutter_tools/src/runner/flutter_command.dart';
|
import 'package:flutter_tools/src/runner/flutter_command.dart';
|
||||||
|
import 'package:flutter_tools/src/web/compile.dart';
|
||||||
|
|
||||||
import '../../src/common.dart';
|
import '../../src/common.dart';
|
||||||
import '../../src/context.dart';
|
import '../../src/context.dart';
|
||||||
|
@ -147,15 +149,9 @@ void main() {
|
||||||
expect(environment.defines, <String, String>{
|
expect(environment.defines, <String, String>{
|
||||||
'TargetFile': 'lib/main.dart',
|
'TargetFile': 'lib/main.dart',
|
||||||
'HasWebPlugins': 'true',
|
'HasWebPlugins': 'true',
|
||||||
'cspMode': 'false',
|
|
||||||
'SourceMaps': 'false',
|
|
||||||
'NativeNullAssertions': 'true',
|
|
||||||
'ServiceWorkerStrategy': 'offline-first',
|
'ServiceWorkerStrategy': 'offline-first',
|
||||||
'Dart2jsDumpInfo': 'false',
|
|
||||||
'Dart2jsNoFrequencyBasedMinification': 'false',
|
|
||||||
'Dart2jsOptimization': 'O3',
|
|
||||||
'BuildMode': 'release',
|
'BuildMode': 'release',
|
||||||
'DartDefines': 'Zm9vPWE=,RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==',
|
'DartDefines': 'Zm9vPWE=',
|
||||||
'DartObfuscation': 'false',
|
'DartObfuscation': 'false',
|
||||||
'TrackWidgetCreation': 'false',
|
'TrackWidgetCreation': 'false',
|
||||||
'TreeShakeIcons': 'true',
|
'TreeShakeIcons': 'true',
|
||||||
|
@ -249,15 +245,8 @@ void main() {
|
||||||
expect(environment.defines, <String, String>{
|
expect(environment.defines, <String, String>{
|
||||||
'TargetFile': 'lib/main.dart',
|
'TargetFile': 'lib/main.dart',
|
||||||
'HasWebPlugins': 'true',
|
'HasWebPlugins': 'true',
|
||||||
'cspMode': 'false',
|
|
||||||
'SourceMaps': 'false',
|
|
||||||
'NativeNullAssertions': 'true',
|
|
||||||
'ServiceWorkerStrategy': 'offline-first',
|
'ServiceWorkerStrategy': 'offline-first',
|
||||||
'Dart2jsDumpInfo': 'false',
|
|
||||||
'Dart2jsNoFrequencyBasedMinification': 'false',
|
|
||||||
'Dart2jsOptimization': 'O4',
|
|
||||||
'BuildMode': 'release',
|
'BuildMode': 'release',
|
||||||
'DartDefines': 'RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==',
|
|
||||||
'DartObfuscation': 'false',
|
'DartObfuscation': 'false',
|
||||||
'TrackWidgetCreation': 'false',
|
'TrackWidgetCreation': 'false',
|
||||||
'TreeShakeIcons': 'true',
|
'TreeShakeIcons': 'true',
|
||||||
|
@ -288,15 +277,17 @@ void main() {
|
||||||
final CommandRunner<void> runner = createTestCommandRunner(buildCommand);
|
final CommandRunner<void> runner = createTestCommandRunner(buildCommand);
|
||||||
setupFileSystemForEndToEndTest(fileSystem);
|
setupFileSystemForEndToEndTest(fileSystem);
|
||||||
await runner.run(<String>['build', 'web', '--no-pub']);
|
await runner.run(<String>['build', 'web', '--no-pub']);
|
||||||
final BuildInfo buildInfo =
|
|
||||||
await buildCommand.webCommand.getBuildInfo(forcedBuildMode: BuildMode.debug);
|
|
||||||
expect(buildInfo.dartDefines, contains('FLUTTER_WEB_AUTO_DETECT=true'));
|
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
Platform: () => fakePlatform,
|
Platform: () => fakePlatform,
|
||||||
FileSystem: () => fileSystem,
|
FileSystem: () => fileSystem,
|
||||||
FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
|
FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
|
||||||
ProcessManager: () => processManager,
|
ProcessManager: () => processManager,
|
||||||
BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)),
|
BuildSystem: () => TestBuildSystem.all(BuildResult(success: true), (Target target, Environment environment) {
|
||||||
|
expect(target, isA<WebServiceWorker>());
|
||||||
|
final List<WebCompilerConfig> configs = (target as WebServiceWorker).compileConfigs;
|
||||||
|
expect(configs.length, 1);
|
||||||
|
expect(configs.first.renderer, WebRendererMode.auto);
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('Web build supports build-name and build-number', () async {
|
testUsingContext('Web build supports build-name and build-number', () async {
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
// 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:file/file.dart';
|
||||||
|
import 'package:file/memory.dart';
|
||||||
|
import 'package:flutter_tools/src/artifacts.dart';
|
||||||
|
import 'package:flutter_tools/src/base/logger.dart';
|
||||||
|
import 'package:flutter_tools/src/base/platform.dart';
|
||||||
|
import 'package:flutter_tools/src/build_info.dart';
|
||||||
|
import 'package:flutter_tools/src/test/flutter_web_platform.dart';
|
||||||
|
import 'package:flutter_tools/src/web/chrome.dart';
|
||||||
|
import 'package:flutter_tools/src/web/compile.dart';
|
||||||
|
import 'package:flutter_tools/src/web/memory_fs.dart';
|
||||||
|
import 'package:shelf/shelf.dart' as shelf;
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../../src/context.dart';
|
||||||
|
import '../../src/fakes.dart';
|
||||||
|
|
||||||
|
class MockServer implements shelf.Server {
|
||||||
|
shelf.Handler? mountedHandler;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> close() async {}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void mount(shelf.Handler handler) {
|
||||||
|
mountedHandler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Uri get url => Uri.parse('');
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
late FileSystem fileSystem;
|
||||||
|
late BufferLogger logger;
|
||||||
|
late Platform platform;
|
||||||
|
late Artifacts artifacts;
|
||||||
|
late ProcessManager processManager;
|
||||||
|
late FakeOperatingSystemUtils operatingSystemUtils;
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
fileSystem = MemoryFileSystem.test();
|
||||||
|
logger = BufferLogger.test();
|
||||||
|
platform = FakePlatform();
|
||||||
|
artifacts = Artifacts.test(fileSystem: fileSystem);
|
||||||
|
processManager = FakeProcessManager.empty();
|
||||||
|
operatingSystemUtils = FakeOperatingSystemUtils();
|
||||||
|
|
||||||
|
for (final HostArtifact artifact in <HostArtifact>[
|
||||||
|
HostArtifact.webPrecompiledCanvaskitAndHtmlSoundSdk,
|
||||||
|
HostArtifact.webPrecompiledCanvaskitAndHtmlSdk,
|
||||||
|
HostArtifact.webPrecompiledCanvaskitSoundSdk,
|
||||||
|
HostArtifact.webPrecompiledCanvaskitSdk,
|
||||||
|
HostArtifact.webPrecompiledSoundSdk,
|
||||||
|
HostArtifact.webPrecompiledSdk,
|
||||||
|
]) {
|
||||||
|
final File artifactFile = artifacts.getHostArtifact(artifact) as File;
|
||||||
|
artifactFile.createSync();
|
||||||
|
artifactFile.writeAsStringSync(artifact.name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('FlutterWebPlatform serves the correct dart_sdk.js for the passed web renderer', () async {
|
||||||
|
final ChromiumLauncher chromiumLauncher = ChromiumLauncher(
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
platform: platform,
|
||||||
|
processManager: processManager,
|
||||||
|
operatingSystemUtils: operatingSystemUtils,
|
||||||
|
browserFinder: (Platform platform, FileSystem filesystem) => 'chrome',
|
||||||
|
logger: logger,
|
||||||
|
);
|
||||||
|
final MockServer server = MockServer();
|
||||||
|
fileSystem.directory('/test').createSync();
|
||||||
|
final FlutterWebPlatform webPlatform = await FlutterWebPlatform.start(
|
||||||
|
'ProjectRoot',
|
||||||
|
buildInfo: const BuildInfo(
|
||||||
|
BuildMode.debug,
|
||||||
|
'',
|
||||||
|
treeShakeIcons: false
|
||||||
|
),
|
||||||
|
webMemoryFS: WebMemoryFS(),
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
logger: logger,
|
||||||
|
chromiumLauncher: chromiumLauncher,
|
||||||
|
artifacts: artifacts,
|
||||||
|
processManager: processManager,
|
||||||
|
webRenderer: WebRendererMode.canvaskit,
|
||||||
|
serverFactory: () async => server,
|
||||||
|
testPackageUri: Uri.parse('test'),
|
||||||
|
);
|
||||||
|
final shelf.Handler? handler = server.mountedHandler;
|
||||||
|
expect(handler, isNotNull);
|
||||||
|
handler!;
|
||||||
|
final shelf.Response response = await handler(shelf.Request(
|
||||||
|
'GET',
|
||||||
|
Uri.parse('http://localhost/dart_sdk.js'),
|
||||||
|
));
|
||||||
|
final String contents = await response.readAsString();
|
||||||
|
expect(contents, HostArtifact.webPrecompiledCanvaskitSoundSdk.name);
|
||||||
|
await webPlatform.close();
|
||||||
|
}, overrides: <Type, Generator>{
|
||||||
|
FileSystem: () => fileSystem,
|
||||||
|
ProcessManager: () => processManager,
|
||||||
|
Logger: () => logger,
|
||||||
|
});
|
||||||
|
}
|
|
@ -32,7 +32,6 @@ import 'package:flutter_tools/src/resident_runner.dart';
|
||||||
import 'package:flutter_tools/src/run_hot.dart';
|
import 'package:flutter_tools/src/run_hot.dart';
|
||||||
import 'package:flutter_tools/src/runner/flutter_command.dart';
|
import 'package:flutter_tools/src/runner/flutter_command.dart';
|
||||||
import 'package:flutter_tools/src/vmservice.dart';
|
import 'package:flutter_tools/src/vmservice.dart';
|
||||||
import 'package:flutter_tools/src/web/compile.dart';
|
|
||||||
import 'package:test/fake.dart';
|
import 'package:test/fake.dart';
|
||||||
import 'package:unified_analytics/unified_analytics.dart' as analytics;
|
import 'package:unified_analytics/unified_analytics.dart' as analytics;
|
||||||
import 'package:vm_service/vm_service.dart';
|
import 'package:vm_service/vm_service.dart';
|
||||||
|
@ -1087,47 +1086,6 @@ void main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
group('dart-defines and web-renderer options', () {
|
|
||||||
late List<String> dartDefines;
|
|
||||||
|
|
||||||
setUp(() {
|
|
||||||
dartDefines = <String>[];
|
|
||||||
});
|
|
||||||
|
|
||||||
test('auto web-renderer with no dart-defines', () {
|
|
||||||
dartDefines = FlutterCommand.updateDartDefines(dartDefines, WebRendererMode.auto);
|
|
||||||
expect(dartDefines, <String>['FLUTTER_WEB_AUTO_DETECT=true']);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('canvaskit web-renderer with no dart-defines', () {
|
|
||||||
dartDefines = FlutterCommand.updateDartDefines(dartDefines, WebRendererMode.canvaskit);
|
|
||||||
expect(dartDefines, <String>['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, <String>['FLUTTER_WEB_AUTO_DETECT=false','FLUTTER_WEB_USE_SKIA=false']);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('auto web-renderer with existing dart-defines', () {
|
|
||||||
dartDefines = <String>['FLUTTER_WEB_USE_SKIA=false'];
|
|
||||||
dartDefines = FlutterCommand.updateDartDefines(dartDefines, WebRendererMode.auto);
|
|
||||||
expect(dartDefines, <String>['FLUTTER_WEB_AUTO_DETECT=true']);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('canvaskit web-renderer with no dart-defines', () {
|
|
||||||
dartDefines = <String>['FLUTTER_WEB_USE_SKIA=false'];
|
|
||||||
dartDefines = FlutterCommand.updateDartDefines(dartDefines, WebRendererMode.canvaskit);
|
|
||||||
expect(dartDefines, <String>['FLUTTER_WEB_AUTO_DETECT=false','FLUTTER_WEB_USE_SKIA=true']);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('html web-renderer with no dart-defines', () {
|
|
||||||
dartDefines = <String>['FLUTTER_WEB_USE_SKIA=true'];
|
|
||||||
dartDefines = FlutterCommand.updateDartDefines(dartDefines, WebRendererMode.html);
|
|
||||||
expect(dartDefines, <String>['FLUTTER_WEB_AUTO_DETECT=false','FLUTTER_WEB_USE_SKIA=false']);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
group('terminal', () {
|
group('terminal', () {
|
||||||
late FakeAnsiTerminal fakeTerminal;
|
late FakeAnsiTerminal fakeTerminal;
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ 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_time_recorder.dart';
|
||||||
import 'package:flutter_tools/src/test/test_wrapper.dart';
|
import 'package:flutter_tools/src/test/test_wrapper.dart';
|
||||||
import 'package:flutter_tools/src/test/watcher.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:stream_channel/stream_channel.dart';
|
||||||
import 'package:vm_service/vm_service.dart';
|
import 'package:vm_service/vm_service.dart';
|
||||||
|
|
||||||
|
@ -1058,6 +1059,24 @@ dev_dependencies:
|
||||||
FileSystem: () => fs,
|
FileSystem: () => fs,
|
||||||
ProcessManager: () => FakeProcessManager.any(),
|
ProcessManager: () => FakeProcessManager.any(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testUsingContext('Passes web renderer into debugging options', () async {
|
||||||
|
final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0);
|
||||||
|
|
||||||
|
final TestCommand testCommand = TestCommand(testRunner: testRunner);
|
||||||
|
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
|
||||||
|
|
||||||
|
await commandRunner.run(const <String>[
|
||||||
|
'test',
|
||||||
|
'--no-pub',
|
||||||
|
'--platform=chrome',
|
||||||
|
'--web-renderer=canvaskit',
|
||||||
|
]);
|
||||||
|
expect(testRunner.lastDebuggingOptionsValue.webRenderer, WebRendererMode.canvaskit);
|
||||||
|
}, overrides: <Type, Generator>{
|
||||||
|
FileSystem: () => fs,
|
||||||
|
ProcessManager: () => FakeProcessManager.any(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,10 +21,10 @@ import '../../src/fake_process_manager.dart';
|
||||||
void main() {
|
void main() {
|
||||||
late FileSystem fileSystem;
|
late FileSystem fileSystem;
|
||||||
late Environment environment;
|
late Environment environment;
|
||||||
late Target fooTarget;
|
late TestTarget fooTarget;
|
||||||
late Target barTarget;
|
late TestTarget barTarget;
|
||||||
late Target fizzTarget;
|
late TestTarget fizzTarget;
|
||||||
late Target sharedTarget;
|
late TestTarget sharedTarget;
|
||||||
late int fooInvocations;
|
late int fooInvocations;
|
||||||
late int barInvocations;
|
late int barInvocations;
|
||||||
late int shared;
|
late int shared;
|
||||||
|
@ -138,6 +138,23 @@ void main() {
|
||||||
json.decode(stampFile.readAsStringSync()));
|
json.decode(stampFile.readAsStringSync()));
|
||||||
|
|
||||||
expect(stampContents, containsPair('inputs', <Object>['/foo.dart']));
|
expect(stampContents, containsPair('inputs', <Object>['/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<String, Object?>? stampContents = castStringKeyedMap(
|
||||||
|
json.decode(stampFile.readAsStringSync()));
|
||||||
|
|
||||||
|
expect(stampContents, containsPair('inputs', <Object>['/foo.dart']));
|
||||||
|
expect(stampContents, containsPair('buildKey', 'fooBuildKey'));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('Creates a BuildResult with inputs and outputs', () async {
|
testWithoutContext('Creates a BuildResult with inputs and outputs', () async {
|
||||||
|
@ -168,6 +185,19 @@ void main() {
|
||||||
expect(fooInvocations, 2);
|
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 {
|
testWithoutContext('does not re-invoke build if input timestamp changes', () async {
|
||||||
final BuildSystem buildSystem = setUpBuildSystem(fileSystem);
|
final BuildSystem buildSystem = setUpBuildSystem(fileSystem);
|
||||||
await buildSystem.build(fooTarget, environment);
|
await buildSystem.build(fooTarget, environment);
|
||||||
|
@ -723,4 +753,7 @@ class TestTarget extends Target {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Source> outputs = <Source>[];
|
List<Source> outputs = <Source>[];
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? buildKey;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
// 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/web/compile.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
group('dart-defines and web-renderer options', () {
|
||||||
|
late List<String> dartDefines;
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
dartDefines = <String>[];
|
||||||
|
});
|
||||||
|
|
||||||
|
test('auto web-renderer with no dart-defines', () {
|
||||||
|
dartDefines = WebRendererMode.auto.updateDartDefines(dartDefines);
|
||||||
|
expect(dartDefines, <String>['FLUTTER_WEB_AUTO_DETECT=true']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('canvaskit web-renderer with no dart-defines', () {
|
||||||
|
dartDefines = WebRendererMode.canvaskit.updateDartDefines(dartDefines);
|
||||||
|
expect(dartDefines, <String>['FLUTTER_WEB_AUTO_DETECT=false','FLUTTER_WEB_USE_SKIA=true']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('html web-renderer with no dart-defines', () {
|
||||||
|
dartDefines = WebRendererMode.html.updateDartDefines(dartDefines);
|
||||||
|
expect(dartDefines, <String>['FLUTTER_WEB_AUTO_DETECT=false','FLUTTER_WEB_USE_SKIA=false']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('auto web-renderer with existing dart-defines', () {
|
||||||
|
dartDefines = <String>['FLUTTER_WEB_USE_SKIA=false'];
|
||||||
|
dartDefines = WebRendererMode.auto.updateDartDefines(dartDefines);
|
||||||
|
expect(dartDefines, <String>['FLUTTER_WEB_AUTO_DETECT=true']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('canvaskit web-renderer with no dart-defines', () {
|
||||||
|
dartDefines = <String>['FLUTTER_WEB_USE_SKIA=false'];
|
||||||
|
dartDefines = WebRendererMode.canvaskit.updateDartDefines(dartDefines);
|
||||||
|
expect(dartDefines, <String>['FLUTTER_WEB_AUTO_DETECT=false','FLUTTER_WEB_USE_SKIA=true']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('html web-renderer with no dart-defines', () {
|
||||||
|
dartDefines = <String>['FLUTTER_WEB_USE_SKIA=true'];
|
||||||
|
dartDefines = WebRendererMode.html.updateDartDefines(dartDefines);
|
||||||
|
expect(dartDefines, <String>['FLUTTER_WEB_AUTO_DETECT=false','FLUTTER_WEB_USE_SKIA=false']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -120,7 +120,9 @@ void main() {
|
||||||
webResources.childFile('index.html')
|
webResources.childFile('index.html')
|
||||||
.createSync(recursive: true);
|
.createSync(recursive: true);
|
||||||
environment.buildDir.childFile('main.dart.js').createSync();
|
environment.buildDir.childFile('main.dart.js').createSync();
|
||||||
await const WebReleaseBundle(WebRendererMode.auto, isWasm: false).build(environment);
|
await WebReleaseBundle(<WebCompilerConfig>[
|
||||||
|
const JsCompilerConfig()
|
||||||
|
]).build(environment);
|
||||||
|
|
||||||
expect(environment.outputDir.childFile('version.json'), exists);
|
expect(environment.outputDir.childFile('version.json'), exists);
|
||||||
}));
|
}));
|
||||||
|
@ -132,7 +134,9 @@ void main() {
|
||||||
final Directory webResources = environment.projectDir.childDirectory('web');
|
final Directory webResources = environment.projectDir.childDirectory('web');
|
||||||
webResources.childFile('index.html').createSync(recursive: true);
|
webResources.childFile('index.html').createSync(recursive: true);
|
||||||
environment.buildDir.childFile('main.dart.js').createSync();
|
environment.buildDir.childFile('main.dart.js').createSync();
|
||||||
await const WebReleaseBundle(WebRendererMode.auto, isWasm: false).build(environment);
|
await WebReleaseBundle(<WebCompilerConfig>[
|
||||||
|
const JsCompilerConfig()
|
||||||
|
]).build(environment);
|
||||||
|
|
||||||
final String versionFile = environment.outputDir
|
final String versionFile = environment.outputDir
|
||||||
.childFile('version.json')
|
.childFile('version.json')
|
||||||
|
@ -150,7 +154,9 @@ void main() {
|
||||||
<!DOCTYPE html><html><base href="$kBaseHrefPlaceholder"><head></head></html>
|
<!DOCTYPE html><html><base href="$kBaseHrefPlaceholder"><head></head></html>
|
||||||
''');
|
''');
|
||||||
environment.buildDir.childFile('main.dart.js').createSync();
|
environment.buildDir.childFile('main.dart.js').createSync();
|
||||||
await const WebReleaseBundle(WebRendererMode.auto, isWasm: false).build(environment);
|
await WebReleaseBundle(<WebCompilerConfig>[
|
||||||
|
const JsCompilerConfig()
|
||||||
|
]).build(environment);
|
||||||
|
|
||||||
expect(environment.outputDir.childFile('index.html').readAsStringSync(), contains('/basehreftest/'));
|
expect(environment.outputDir.childFile('index.html').readAsStringSync(), contains('/basehreftest/'));
|
||||||
}));
|
}));
|
||||||
|
@ -163,7 +169,9 @@ void main() {
|
||||||
<!DOCTYPE html><html><head><base href='/basehreftest/'></head></html>
|
<!DOCTYPE html><html><head><base href='/basehreftest/'></head></html>
|
||||||
''');
|
''');
|
||||||
environment.buildDir.childFile('main.dart.js').createSync();
|
environment.buildDir.childFile('main.dart.js').createSync();
|
||||||
await const WebReleaseBundle(WebRendererMode.auto, isWasm: false).build(environment);
|
await WebReleaseBundle(<WebCompilerConfig>[
|
||||||
|
const JsCompilerConfig()
|
||||||
|
]).build(environment);
|
||||||
|
|
||||||
expect(environment.outputDir.childFile('index.html').readAsStringSync(), contains('/basehreftest/'));
|
expect(environment.outputDir.childFile('index.html').readAsStringSync(), contains('/basehreftest/'));
|
||||||
}));
|
}));
|
||||||
|
@ -185,7 +193,9 @@ void main() {
|
||||||
.writeAsStringSync('A');
|
.writeAsStringSync('A');
|
||||||
environment.buildDir.childFile('main.dart.js').createSync();
|
environment.buildDir.childFile('main.dart.js').createSync();
|
||||||
|
|
||||||
await const WebReleaseBundle(WebRendererMode.auto, isWasm: false).build(environment);
|
await WebReleaseBundle(<WebCompilerConfig>[
|
||||||
|
const JsCompilerConfig()
|
||||||
|
]).build(environment);
|
||||||
|
|
||||||
expect(environment.outputDir.childFile('foo.txt')
|
expect(environment.outputDir.childFile('foo.txt')
|
||||||
.readAsStringSync(), 'A');
|
.readAsStringSync(), 'A');
|
||||||
|
@ -197,7 +207,9 @@ void main() {
|
||||||
// Update to arbitrary resource file triggers rebuild.
|
// Update to arbitrary resource file triggers rebuild.
|
||||||
webResources.childFile('foo.txt').writeAsStringSync('B');
|
webResources.childFile('foo.txt').writeAsStringSync('B');
|
||||||
|
|
||||||
await const WebReleaseBundle(WebRendererMode.auto, isWasm: false).build(environment);
|
await WebReleaseBundle(<WebCompilerConfig>[
|
||||||
|
const JsCompilerConfig()
|
||||||
|
]).build(environment);
|
||||||
|
|
||||||
expect(environment.outputDir.childFile('foo.txt')
|
expect(environment.outputDir.childFile('foo.txt')
|
||||||
.readAsStringSync(), 'B');
|
.readAsStringSync(), 'B');
|
||||||
|
@ -207,6 +219,36 @@ void main() {
|
||||||
contains('flutter_service_worker.js?v='),
|
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(<WebCompilerConfig>[
|
||||||
|
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(<WebCompilerConfig>[
|
||||||
|
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 {
|
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'))
|
final File mainFile = globals.fs.file(globals.fs.path.join('other', 'lib', 'main.dart'))
|
||||||
..createSync(recursive: true)
|
..createSync(recursive: true)
|
||||||
|
@ -353,6 +395,7 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'-Ddart.vm.profile=true',
|
'-Ddart.vm.profile=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-o',
|
'-o',
|
||||||
environment.buildDir.childFile('app.dill').absolute.path,
|
environment.buildDir.childFile('app.dill').absolute.path,
|
||||||
|
@ -365,6 +408,7 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'-Ddart.vm.profile=true',
|
'-Ddart.vm.profile=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-minify',
|
'--no-minify',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-O4',
|
'-O4',
|
||||||
|
@ -375,7 +419,12 @@ void main() {
|
||||||
]
|
]
|
||||||
));
|
));
|
||||||
|
|
||||||
await Dart2JSTarget(WebRendererMode.auto).build(environment);
|
await Dart2JSTarget(
|
||||||
|
const JsCompilerConfig(
|
||||||
|
csp: true,
|
||||||
|
sourceMaps: false,
|
||||||
|
)
|
||||||
|
).build(environment);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
ProcessManager: () => processManager,
|
ProcessManager: () => processManager,
|
||||||
}));
|
}));
|
||||||
|
@ -387,6 +436,7 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'-Ddart.vm.profile=true',
|
'-Ddart.vm.profile=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-o',
|
'-o',
|
||||||
environment.buildDir.childFile('app.dill').absolute.path,
|
environment.buildDir.childFile('app.dill').absolute.path,
|
||||||
|
@ -399,6 +449,7 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'-Ddart.vm.profile=true',
|
'-Ddart.vm.profile=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-minify',
|
'--no-minify',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-O4',
|
'-O4',
|
||||||
|
@ -408,7 +459,11 @@ void main() {
|
||||||
]
|
]
|
||||||
));
|
));
|
||||||
|
|
||||||
await Dart2JSTarget(WebRendererMode.auto).build(environment);
|
await Dart2JSTarget(
|
||||||
|
const JsCompilerConfig(
|
||||||
|
sourceMaps: false,
|
||||||
|
)
|
||||||
|
).build(environment);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
ProcessManager: () => processManager,
|
ProcessManager: () => processManager,
|
||||||
}));
|
}));
|
||||||
|
@ -421,6 +476,7 @@ void main() {
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'--enable-experiment=non-nullable',
|
'--enable-experiment=non-nullable',
|
||||||
'-Ddart.vm.profile=true',
|
'-Ddart.vm.profile=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-o',
|
'-o',
|
||||||
environment.buildDir.childFile('app.dill').absolute.path,
|
environment.buildDir.childFile('app.dill').absolute.path,
|
||||||
|
@ -434,6 +490,7 @@ void main() {
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'--enable-experiment=non-nullable',
|
'--enable-experiment=non-nullable',
|
||||||
'-Ddart.vm.profile=true',
|
'-Ddart.vm.profile=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-minify',
|
'--no-minify',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-O4',
|
'-O4',
|
||||||
|
@ -443,7 +500,11 @@ void main() {
|
||||||
]
|
]
|
||||||
));
|
));
|
||||||
|
|
||||||
await Dart2JSTarget(WebRendererMode.auto).build(environment);
|
await Dart2JSTarget(
|
||||||
|
const JsCompilerConfig(
|
||||||
|
sourceMaps: false,
|
||||||
|
)
|
||||||
|
).build(environment);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
ProcessManager: () => processManager,
|
ProcessManager: () => processManager,
|
||||||
}));
|
}));
|
||||||
|
@ -454,6 +515,7 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'-Ddart.vm.profile=true',
|
'-Ddart.vm.profile=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-o',
|
'-o',
|
||||||
environment.buildDir.childFile('app.dill').absolute.path,
|
environment.buildDir.childFile('app.dill').absolute.path,
|
||||||
|
@ -466,6 +528,7 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'-Ddart.vm.profile=true',
|
'-Ddart.vm.profile=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-minify',
|
'--no-minify',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-O4',
|
'-O4',
|
||||||
|
@ -475,7 +538,11 @@ void main() {
|
||||||
]
|
]
|
||||||
));
|
));
|
||||||
|
|
||||||
await Dart2JSTarget(WebRendererMode.auto).build(environment);
|
await Dart2JSTarget(
|
||||||
|
const JsCompilerConfig(
|
||||||
|
sourceMaps: false,
|
||||||
|
)
|
||||||
|
).build(environment);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
ProcessManager: () => processManager,
|
ProcessManager: () => processManager,
|
||||||
}));
|
}));
|
||||||
|
@ -486,6 +553,7 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'-Ddart.vm.product=true',
|
'-Ddart.vm.product=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-o',
|
'-o',
|
||||||
environment.buildDir.childFile('app.dill').absolute.path,
|
environment.buildDir.childFile('app.dill').absolute.path,
|
||||||
|
@ -498,6 +566,7 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'-Ddart.vm.product=true',
|
'-Ddart.vm.product=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-O4',
|
'-O4',
|
||||||
'-o',
|
'-o',
|
||||||
|
@ -506,7 +575,11 @@ void main() {
|
||||||
]
|
]
|
||||||
));
|
));
|
||||||
|
|
||||||
await Dart2JSTarget(WebRendererMode.auto).build(environment);
|
await Dart2JSTarget(
|
||||||
|
const JsCompilerConfig(
|
||||||
|
sourceMaps: false,
|
||||||
|
)
|
||||||
|
).build(environment);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
ProcessManager: () => processManager,
|
ProcessManager: () => processManager,
|
||||||
}));
|
}));
|
||||||
|
@ -518,6 +591,7 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'-Ddart.vm.product=true',
|
'-Ddart.vm.product=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--native-null-assertions',
|
'--native-null-assertions',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-o',
|
'-o',
|
||||||
|
@ -531,6 +605,7 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'-Ddart.vm.product=true',
|
'-Ddart.vm.product=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--native-null-assertions',
|
'--native-null-assertions',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-O4',
|
'-O4',
|
||||||
|
@ -540,7 +615,12 @@ void main() {
|
||||||
]
|
]
|
||||||
));
|
));
|
||||||
|
|
||||||
await Dart2JSTarget(WebRendererMode.auto).build(environment);
|
await Dart2JSTarget(
|
||||||
|
const JsCompilerConfig(
|
||||||
|
nativeNullAssertions: true,
|
||||||
|
sourceMaps: false,
|
||||||
|
)
|
||||||
|
).build(environment);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
ProcessManager: () => processManager,
|
ProcessManager: () => processManager,
|
||||||
}));
|
}));
|
||||||
|
@ -552,6 +632,7 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'-Ddart.vm.product=true',
|
'-Ddart.vm.product=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-o',
|
'-o',
|
||||||
environment.buildDir.childFile('app.dill').absolute.path,
|
environment.buildDir.childFile('app.dill').absolute.path,
|
||||||
|
@ -564,6 +645,7 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'-Ddart.vm.product=true',
|
'-Ddart.vm.product=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-O3',
|
'-O3',
|
||||||
'-o',
|
'-o',
|
||||||
|
@ -572,7 +654,12 @@ void main() {
|
||||||
]
|
]
|
||||||
));
|
));
|
||||||
|
|
||||||
await Dart2JSTarget(WebRendererMode.auto).build(environment);
|
await Dart2JSTarget(
|
||||||
|
const JsCompilerConfig(
|
||||||
|
optimizationLevel: 'O3',
|
||||||
|
sourceMaps: false,
|
||||||
|
)
|
||||||
|
).build(environment);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
ProcessManager: () => processManager,
|
ProcessManager: () => processManager,
|
||||||
}));
|
}));
|
||||||
|
@ -583,6 +670,7 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'-Ddart.vm.product=true',
|
'-Ddart.vm.product=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-o',
|
'-o',
|
||||||
environment.buildDir.childFile('app.dill').absolute.path,
|
environment.buildDir.childFile('app.dill').absolute.path,
|
||||||
|
@ -598,6 +686,7 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'-Ddart.vm.product=true',
|
'-Ddart.vm.product=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-O4',
|
'-O4',
|
||||||
'-o',
|
'-o',
|
||||||
|
@ -606,7 +695,11 @@ void main() {
|
||||||
]
|
]
|
||||||
));
|
));
|
||||||
|
|
||||||
await Dart2JSTarget(WebRendererMode.auto).build(environment);
|
await Dart2JSTarget(
|
||||||
|
const JsCompilerConfig(
|
||||||
|
sourceMaps: false,
|
||||||
|
)
|
||||||
|
).build(environment);
|
||||||
|
|
||||||
expect(environment.buildDir.childFile('dart2js.d'), exists);
|
expect(environment.buildDir.childFile('dart2js.d'), exists);
|
||||||
final Depfile depfile = environment.depFileService.parse(environment.buildDir.childFile('dart2js.d'));
|
final Depfile depfile = environment.depFileService.parse(environment.buildDir.childFile('dart2js.d'));
|
||||||
|
@ -627,6 +720,7 @@ void main() {
|
||||||
'-Ddart.vm.product=true',
|
'-Ddart.vm.product=true',
|
||||||
'-DFOO=bar',
|
'-DFOO=bar',
|
||||||
'-DBAZ=qux',
|
'-DBAZ=qux',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-o',
|
'-o',
|
||||||
environment.buildDir.childFile('app.dill').absolute.path,
|
environment.buildDir.childFile('app.dill').absolute.path,
|
||||||
|
@ -641,6 +735,7 @@ void main() {
|
||||||
'-Ddart.vm.product=true',
|
'-Ddart.vm.product=true',
|
||||||
'-DFOO=bar',
|
'-DFOO=bar',
|
||||||
'-DBAZ=qux',
|
'-DBAZ=qux',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-O4',
|
'-O4',
|
||||||
'-o',
|
'-o',
|
||||||
|
@ -649,7 +744,11 @@ void main() {
|
||||||
]
|
]
|
||||||
));
|
));
|
||||||
|
|
||||||
await Dart2JSTarget(WebRendererMode.auto).build(environment);
|
await Dart2JSTarget(
|
||||||
|
const JsCompilerConfig(
|
||||||
|
sourceMaps: false,
|
||||||
|
)
|
||||||
|
).build(environment);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
ProcessManager: () => processManager,
|
ProcessManager: () => processManager,
|
||||||
}));
|
}));
|
||||||
|
@ -661,6 +760,7 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'-Ddart.vm.product=true',
|
'-Ddart.vm.product=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'-o',
|
'-o',
|
||||||
environment.buildDir.childFile('app.dill').absolute.path,
|
environment.buildDir.childFile('app.dill').absolute.path,
|
||||||
'--packages=.dart_tool/package_config.json',
|
'--packages=.dart_tool/package_config.json',
|
||||||
|
@ -672,6 +772,7 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'-Ddart.vm.product=true',
|
'-Ddart.vm.product=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'-O4',
|
'-O4',
|
||||||
'-o',
|
'-o',
|
||||||
environment.buildDir.childFile('main.dart.js').absolute.path,
|
environment.buildDir.childFile('main.dart.js').absolute.path,
|
||||||
|
@ -679,7 +780,9 @@ void main() {
|
||||||
]
|
]
|
||||||
));
|
));
|
||||||
|
|
||||||
await Dart2JSTarget(WebRendererMode.auto).build(environment);
|
await Dart2JSTarget(
|
||||||
|
const JsCompilerConfig()
|
||||||
|
).build(environment);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
ProcessManager: () => processManager,
|
ProcessManager: () => processManager,
|
||||||
}));
|
}));
|
||||||
|
@ -694,6 +797,7 @@ void main() {
|
||||||
'-Ddart.vm.profile=true',
|
'-Ddart.vm.profile=true',
|
||||||
'-DFOO=bar',
|
'-DFOO=bar',
|
||||||
'-DBAZ=qux',
|
'-DBAZ=qux',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-o',
|
'-o',
|
||||||
environment.buildDir.childFile('app.dill').absolute.path,
|
environment.buildDir.childFile('app.dill').absolute.path,
|
||||||
|
@ -708,6 +812,7 @@ void main() {
|
||||||
'-Ddart.vm.profile=true',
|
'-Ddart.vm.profile=true',
|
||||||
'-DFOO=bar',
|
'-DFOO=bar',
|
||||||
'-DBAZ=qux',
|
'-DBAZ=qux',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-minify',
|
'--no-minify',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-O4',
|
'-O4',
|
||||||
|
@ -717,7 +822,11 @@ void main() {
|
||||||
]
|
]
|
||||||
));
|
));
|
||||||
|
|
||||||
await Dart2JSTarget(WebRendererMode.auto).build(environment);
|
await Dart2JSTarget(
|
||||||
|
const JsCompilerConfig(
|
||||||
|
sourceMaps: false,
|
||||||
|
)
|
||||||
|
).build(environment);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
ProcessManager: () => processManager,
|
ProcessManager: () => processManager,
|
||||||
}));
|
}));
|
||||||
|
@ -729,6 +838,7 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'-Ddart.vm.profile=true',
|
'-Ddart.vm.profile=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-o',
|
'-o',
|
||||||
environment.buildDir.childFile('app.dill').absolute.path,
|
environment.buildDir.childFile('app.dill').absolute.path,
|
||||||
|
@ -741,6 +851,7 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'-Ddart.vm.profile=true',
|
'-Ddart.vm.profile=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-minify',
|
'--no-minify',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-O4',
|
'-O4',
|
||||||
|
@ -751,7 +862,12 @@ void main() {
|
||||||
]
|
]
|
||||||
));
|
));
|
||||||
|
|
||||||
await Dart2JSTarget(WebRendererMode.canvaskit).build(environment);
|
await Dart2JSTarget(
|
||||||
|
const JsCompilerConfig(
|
||||||
|
dumpInfo: true,
|
||||||
|
sourceMaps: false,
|
||||||
|
)
|
||||||
|
).build(environment);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
ProcessManager: () => processManager,
|
ProcessManager: () => processManager,
|
||||||
}));
|
}));
|
||||||
|
@ -763,6 +879,7 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'-Ddart.vm.profile=true',
|
'-Ddart.vm.profile=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-o',
|
'-o',
|
||||||
environment.buildDir.childFile('app.dill').absolute.path,
|
environment.buildDir.childFile('app.dill').absolute.path,
|
||||||
|
@ -775,6 +892,7 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2jsLinuxArgs,
|
..._kDart2jsLinuxArgs,
|
||||||
'-Ddart.vm.profile=true',
|
'-Ddart.vm.profile=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=true',
|
||||||
'--no-minify',
|
'--no-minify',
|
||||||
'--no-source-maps',
|
'--no-source-maps',
|
||||||
'-O4',
|
'-O4',
|
||||||
|
@ -785,7 +903,12 @@ void main() {
|
||||||
]
|
]
|
||||||
));
|
));
|
||||||
|
|
||||||
await Dart2JSTarget(WebRendererMode.canvaskit).build(environment);
|
await Dart2JSTarget(
|
||||||
|
const JsCompilerConfig(
|
||||||
|
noFrequencyBasedMinification: true,
|
||||||
|
sourceMaps: false,
|
||||||
|
)
|
||||||
|
).build(environment);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
ProcessManager: () => processManager,
|
ProcessManager: () => processManager,
|
||||||
}));
|
}));
|
||||||
|
@ -804,6 +927,8 @@ void main() {
|
||||||
'-Ddart.vm.profile=true',
|
'-Ddart.vm.profile=true',
|
||||||
'-DFOO=bar',
|
'-DFOO=bar',
|
||||||
'-DBAZ=qux',
|
'-DBAZ=qux',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=false',
|
||||||
|
'-DFLUTTER_WEB_USE_SKIA=true',
|
||||||
'--depfile=${depFile.absolute.path}',
|
'--depfile=${depFile.absolute.path}',
|
||||||
environment.buildDir.childFile('main.dart').absolute.path,
|
environment.buildDir.childFile('main.dart').absolute.path,
|
||||||
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
|
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
|
||||||
|
@ -820,7 +945,11 @@ void main() {
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
await Dart2WasmTarget(WebRendererMode.canvaskit).build(environment);
|
await Dart2WasmTarget(
|
||||||
|
const WasmCompilerConfig(
|
||||||
|
renderer: WebRendererMode.canvaskit
|
||||||
|
)
|
||||||
|
).build(environment);
|
||||||
|
|
||||||
expect(outputJsFile.existsSync(), isFalse);
|
expect(outputJsFile.existsSync(), isFalse);
|
||||||
final File movedJsFile = environment.buildDir.childFile('main.dart.mjs');
|
final File movedJsFile = environment.buildDir.childFile('main.dart.mjs');
|
||||||
|
@ -842,6 +971,8 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2WasmLinuxArgs,
|
..._kDart2WasmLinuxArgs,
|
||||||
'-Ddart.vm.product=true',
|
'-Ddart.vm.product=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=false',
|
||||||
|
'-DFLUTTER_WEB_USE_SKIA=true',
|
||||||
'--omit-type-checks',
|
'--omit-type-checks',
|
||||||
'--depfile=${depFile.absolute.path}',
|
'--depfile=${depFile.absolute.path}',
|
||||||
environment.buildDir.childFile('main.dart').absolute.path,
|
environment.buildDir.childFile('main.dart').absolute.path,
|
||||||
|
@ -859,7 +990,12 @@ void main() {
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
await Dart2WasmTarget(WebRendererMode.canvaskit).build(environment);
|
await Dart2WasmTarget(
|
||||||
|
const WasmCompilerConfig(
|
||||||
|
omitTypeChecks: true,
|
||||||
|
renderer: WebRendererMode.canvaskit
|
||||||
|
)
|
||||||
|
).build(environment);
|
||||||
|
|
||||||
expect(outputJsFile.existsSync(), isFalse);
|
expect(outputJsFile.existsSync(), isFalse);
|
||||||
final File movedJsFile = environment.buildDir.childFile('main.dart.mjs');
|
final File movedJsFile = environment.buildDir.childFile('main.dart.mjs');
|
||||||
|
@ -880,6 +1016,8 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2WasmLinuxArgs,
|
..._kDart2WasmLinuxArgs,
|
||||||
'-Ddart.vm.product=true',
|
'-Ddart.vm.product=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=false',
|
||||||
|
'-DFLUTTER_WEB_USE_SKIA=true',
|
||||||
'--depfile=${depFile.absolute.path}',
|
'--depfile=${depFile.absolute.path}',
|
||||||
environment.buildDir.childFile('main.dart').absolute.path,
|
environment.buildDir.childFile('main.dart').absolute.path,
|
||||||
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
|
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
|
||||||
|
@ -894,7 +1032,12 @@ void main() {
|
||||||
environment.buildDir.childFile('main.dart.wasm').absolute.path,
|
environment.buildDir.childFile('main.dart.wasm').absolute.path,
|
||||||
]));
|
]));
|
||||||
|
|
||||||
await Dart2WasmTarget(WebRendererMode.canvaskit).build(environment);
|
await Dart2WasmTarget(
|
||||||
|
const WasmCompilerConfig(
|
||||||
|
wasmOpt: WasmOptLevel.debug,
|
||||||
|
renderer: WebRendererMode.canvaskit
|
||||||
|
)
|
||||||
|
).build(environment);
|
||||||
|
|
||||||
expect(outputJsFile.existsSync(), isFalse);
|
expect(outputJsFile.existsSync(), isFalse);
|
||||||
final File movedJsFile = environment.buildDir.childFile('main.dart.mjs');
|
final File movedJsFile = environment.buildDir.childFile('main.dart.mjs');
|
||||||
|
@ -915,12 +1058,19 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2WasmLinuxArgs,
|
..._kDart2WasmLinuxArgs,
|
||||||
'-Ddart.vm.product=true',
|
'-Ddart.vm.product=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=false',
|
||||||
|
'-DFLUTTER_WEB_USE_SKIA=true',
|
||||||
'--depfile=${depFile.absolute.path}',
|
'--depfile=${depFile.absolute.path}',
|
||||||
environment.buildDir.childFile('main.dart').absolute.path,
|
environment.buildDir.childFile('main.dart').absolute.path,
|
||||||
environment.buildDir.childFile('main.dart.wasm').absolute.path,
|
environment.buildDir.childFile('main.dart.wasm').absolute.path,
|
||||||
], onRun: (_) => outputJsFile..createSync()..writeAsStringSync('foo')));
|
], onRun: (_) => outputJsFile..createSync()..writeAsStringSync('foo')));
|
||||||
|
|
||||||
await Dart2WasmTarget(WebRendererMode.canvaskit).build(environment);
|
await Dart2WasmTarget(
|
||||||
|
const WasmCompilerConfig(
|
||||||
|
wasmOpt: WasmOptLevel.none,
|
||||||
|
renderer: WebRendererMode.canvaskit
|
||||||
|
)
|
||||||
|
).build(environment);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
ProcessManager: () => processManager,
|
ProcessManager: () => processManager,
|
||||||
}));
|
}));
|
||||||
|
@ -935,6 +1085,9 @@ void main() {
|
||||||
command: <String>[
|
command: <String>[
|
||||||
..._kDart2WasmLinuxArgs,
|
..._kDart2WasmLinuxArgs,
|
||||||
'-Ddart.vm.product=true',
|
'-Ddart.vm.product=true',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=false',
|
||||||
|
'-DFLUTTER_WEB_USE_SKIA=false',
|
||||||
|
'-DFLUTTER_WEB_USE_SKWASM=true',
|
||||||
'--import-shared-memory',
|
'--import-shared-memory',
|
||||||
'--shared-memory-max-pages=32768',
|
'--shared-memory-max-pages=32768',
|
||||||
'--depfile=${depFile.absolute.path}',
|
'--depfile=${depFile.absolute.path}',
|
||||||
|
@ -953,7 +1106,11 @@ void main() {
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
await Dart2WasmTarget(WebRendererMode.skwasm).build(environment);
|
await Dart2WasmTarget(
|
||||||
|
const WasmCompilerConfig(
|
||||||
|
renderer: WebRendererMode.skwasm,
|
||||||
|
)
|
||||||
|
).build(environment);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
ProcessManager: () => processManager,
|
ProcessManager: () => processManager,
|
||||||
}));
|
}));
|
||||||
|
@ -1001,7 +1158,9 @@ void main() {
|
||||||
environment.outputDir.childDirectory('a').childFile('a.txt')
|
environment.outputDir.childDirectory('a').childFile('a.txt')
|
||||||
..createSync(recursive: true)
|
..createSync(recursive: true)
|
||||||
..writeAsStringSync('A');
|
..writeAsStringSync('A');
|
||||||
await WebServiceWorker(globals.fs, WebRendererMode.auto, isWasm: false).build(environment);
|
await WebServiceWorker(globals.fs, <WebCompilerConfig>[
|
||||||
|
const JsCompilerConfig()
|
||||||
|
]).build(environment);
|
||||||
|
|
||||||
expect(environment.outputDir.childFile('flutter_service_worker.js'), exists);
|
expect(environment.outputDir.childFile('flutter_service_worker.js'), exists);
|
||||||
// Contains file hash.
|
// Contains file hash.
|
||||||
|
@ -1024,7 +1183,9 @@ void main() {
|
||||||
.childFile('assets/index.html')
|
.childFile('assets/index.html')
|
||||||
..createSync(recursive: true)
|
..createSync(recursive: true)
|
||||||
..writeAsStringSync('A');
|
..writeAsStringSync('A');
|
||||||
await WebServiceWorker(globals.fs, WebRendererMode.auto, isWasm: false).build(environment);
|
await WebServiceWorker(globals.fs, <WebCompilerConfig>[
|
||||||
|
const JsCompilerConfig()
|
||||||
|
]).build(environment);
|
||||||
|
|
||||||
expect(environment.outputDir.childFile('flutter_service_worker.js'), exists);
|
expect(environment.outputDir.childFile('flutter_service_worker.js'), exists);
|
||||||
// Contains the same file hash for both `/` and the root index.html file.
|
// Contains the same file hash for both `/` and the root index.html file.
|
||||||
|
@ -1046,7 +1207,9 @@ void main() {
|
||||||
environment.outputDir
|
environment.outputDir
|
||||||
.childFile('main.dart.js.map')
|
.childFile('main.dart.js.map')
|
||||||
.createSync(recursive: true);
|
.createSync(recursive: true);
|
||||||
await WebServiceWorker(globals.fs, WebRendererMode.auto, isWasm: false).build(environment);
|
await WebServiceWorker(globals.fs, <WebCompilerConfig>[
|
||||||
|
const JsCompilerConfig()
|
||||||
|
]).build(environment);
|
||||||
|
|
||||||
// No caching of source maps.
|
// No caching of source maps.
|
||||||
expect(environment.outputDir.childFile('flutter_service_worker.js').readAsStringSync(),
|
expect(environment.outputDir.childFile('flutter_service_worker.js').readAsStringSync(),
|
||||||
|
@ -1056,24 +1219,12 @@ void main() {
|
||||||
contains('"main.dart.js"'));
|
contains('"main.dart.js"'));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
test('wasm build copies and generates specific files', () => testbed.run(() async {
|
test('WebBuiltInAssets copies over canvaskit again if the web sdk changes', () => 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')
|
final File canvasKitInput = globals.fs.file('bin/cache/flutter_web_sdk/canvaskit/canvaskit.wasm')
|
||||||
..createSync(recursive: true);
|
..createSync(recursive: true);
|
||||||
canvasKitInput.writeAsStringSync('foo', flush: true);
|
canvasKitInput.writeAsStringSync('foo', flush: true);
|
||||||
|
|
||||||
await WebBuiltInAssets(globals.fs, WebRendererMode.auto, isWasm: true).build(environment);
|
await WebBuiltInAssets(globals.fs).build(environment);
|
||||||
|
|
||||||
final File canvasKitOutputBefore = environment.outputDir.childDirectory('canvaskit')
|
final File canvasKitOutputBefore = environment.outputDir.childDirectory('canvaskit')
|
||||||
.childFile('canvaskit.wasm');
|
.childFile('canvaskit.wasm');
|
||||||
|
@ -1082,7 +1233,7 @@ void main() {
|
||||||
|
|
||||||
canvasKitInput.writeAsStringSync('bar', flush: true);
|
canvasKitInput.writeAsStringSync('bar', flush: true);
|
||||||
|
|
||||||
await WebBuiltInAssets(globals.fs, WebRendererMode.auto, isWasm: true).build(environment);
|
await WebBuiltInAssets(globals.fs).build(environment);
|
||||||
|
|
||||||
final File canvasKitOutputAfter = environment.outputDir.childDirectory('canvaskit')
|
final File canvasKitOutputAfter = environment.outputDir.childDirectory('canvaskit')
|
||||||
.childFile('canvaskit.wasm');
|
.childFile('canvaskit.wasm');
|
||||||
|
|
|
@ -9,6 +9,7 @@ import 'package:flutter_tools/src/base/logger.dart';
|
||||||
import 'package:flutter_tools/src/base/platform.dart';
|
import 'package:flutter_tools/src/base/platform.dart';
|
||||||
import 'package:flutter_tools/src/build_info.dart';
|
import 'package:flutter_tools/src/build_info.dart';
|
||||||
import 'package:flutter_tools/src/test/web_test_compiler.dart';
|
import 'package:flutter_tools/src/test/web_test_compiler.dart';
|
||||||
|
import 'package:flutter_tools/src/web/compile.dart';
|
||||||
import 'package:test/expect.dart';
|
import 'package:test/expect.dart';
|
||||||
|
|
||||||
import '../../src/context.dart';
|
import '../../src/context.dart';
|
||||||
|
@ -44,6 +45,8 @@ void main() {
|
||||||
'--incremental',
|
'--incremental',
|
||||||
'--target=dartdevc',
|
'--target=dartdevc',
|
||||||
'--experimental-emit-debug-metadata',
|
'--experimental-emit-debug-metadata',
|
||||||
|
'-DFLUTTER_WEB_AUTO_DETECT=false',
|
||||||
|
'-DFLUTTER_WEB_USE_SKIA=true',
|
||||||
'--output-dill',
|
'--output-dill',
|
||||||
'build/out',
|
'build/out',
|
||||||
'--packages',
|
'--packages',
|
||||||
|
@ -87,6 +90,7 @@ void main() {
|
||||||
testOutputDir: 'build',
|
testOutputDir: 'build',
|
||||||
testFiles: <String>['project/test/fake_test.dart'],
|
testFiles: <String>['project/test/fake_test.dart'],
|
||||||
buildInfo: buildInfo,
|
buildInfo: buildInfo,
|
||||||
|
webRenderer: WebRendererMode.canvaskit,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(processManager.hasRemainingExpectations, isFalse);
|
expect(processManager.hasRemainingExpectations, isFalse);
|
||||||
|
|
|
@ -43,16 +43,11 @@ void main() {
|
||||||
testUsingContext('WebBuilder sets environment on success', () async {
|
testUsingContext('WebBuilder sets environment on success', () async {
|
||||||
final TestBuildSystem buildSystem =
|
final TestBuildSystem buildSystem =
|
||||||
TestBuildSystem.all(BuildResult(success: true), (Target target, Environment environment) {
|
TestBuildSystem.all(BuildResult(success: true), (Target target, Environment environment) {
|
||||||
final WebServiceWorker webServiceWorker = target as WebServiceWorker;
|
expect(target, isA<WebServiceWorker>());
|
||||||
expect(webServiceWorker.isWasm, isTrue, reason: 'should be wasm');
|
|
||||||
expect(webServiceWorker.webRenderer, WebRendererMode.auto);
|
|
||||||
|
|
||||||
expect(environment.defines, <String, String>{
|
expect(environment.defines, <String, String>{
|
||||||
'TargetFile': 'target',
|
'TargetFile': 'target',
|
||||||
'HasWebPlugins': 'false',
|
'HasWebPlugins': 'false',
|
||||||
'ServiceWorkerStrategy': ServiceWorkerStrategy.offlineFirst.cliName,
|
'ServiceWorkerStrategy': ServiceWorkerStrategy.offlineFirst.cliName,
|
||||||
'WasmOmitTypeChecks': 'false',
|
|
||||||
'RunWasmOpt': 'none',
|
|
||||||
'BuildMode': 'debug',
|
'BuildMode': 'debug',
|
||||||
'DartObfuscation': 'false',
|
'DartObfuscation': 'false',
|
||||||
'TrackWidgetCreation': 'true',
|
'TrackWidgetCreation': 'true',
|
||||||
|
@ -77,10 +72,16 @@ void main() {
|
||||||
'target',
|
'target',
|
||||||
BuildInfo.debug,
|
BuildInfo.debug,
|
||||||
ServiceWorkerStrategy.offlineFirst,
|
ServiceWorkerStrategy.offlineFirst,
|
||||||
compilerConfig: const WasmCompilerConfig(
|
compilerConfigs: <WebCompilerConfig>[
|
||||||
omitTypeChecks: false,
|
const WasmCompilerConfig(
|
||||||
wasmOpt: WasmOptLevel.none,
|
wasmOpt: WasmOptLevel.none,
|
||||||
),
|
renderer: WebRendererMode.skwasm,
|
||||||
|
),
|
||||||
|
const JsCompilerConfig.run(
|
||||||
|
nativeNullAssertions: true,
|
||||||
|
renderer: WebRendererMode.canvaskit,
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(logger.statusText, contains('Compiling target for the Web...'));
|
expect(logger.statusText, contains('Compiling target for the Web...'));
|
||||||
|
@ -102,7 +103,7 @@ void main() {
|
||||||
label: 'web-compile',
|
label: 'web-compile',
|
||||||
parameters: CustomDimensions(
|
parameters: CustomDimensions(
|
||||||
buildEventSettings:
|
buildEventSettings:
|
||||||
'RunWasmOpt: none; WasmOmitTypeChecks: false; wasm-compile: true; web-renderer: auto;',
|
'RunWasmOpt: none; WasmOmitTypeChecks: false; web-renderer: skwasm,canvaskit; web-target: wasm,js;',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -115,7 +116,7 @@ void main() {
|
||||||
Event.flutterBuildInfo(
|
Event.flutterBuildInfo(
|
||||||
label: 'web-compile',
|
label: 'web-compile',
|
||||||
buildType: 'web',
|
buildType: 'web',
|
||||||
settings: 'RunWasmOpt: none; WasmOmitTypeChecks: false; wasm-compile: true; web-renderer: auto;',
|
settings: 'RunWasmOpt: none; WasmOmitTypeChecks: false; web-renderer: skwasm,canvaskit; web-target: wasm,js;',
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
|
@ -123,12 +124,12 @@ void main() {
|
||||||
// Sends timing event.
|
// Sends timing event.
|
||||||
final TestTimingEvent timingEvent = testUsage.timings.single;
|
final TestTimingEvent timingEvent = testUsage.timings.single;
|
||||||
expect(timingEvent.category, 'build');
|
expect(timingEvent.category, 'build');
|
||||||
expect(timingEvent.variableName, 'dart2wasm');
|
expect(timingEvent.variableName, 'dual-compile');
|
||||||
expect(
|
expect(
|
||||||
analyticsTimingEventExists(
|
analyticsTimingEventExists(
|
||||||
sentEvents: fakeAnalytics.sentEvents,
|
sentEvents: fakeAnalytics.sentEvents,
|
||||||
workflow: 'build',
|
workflow: 'build',
|
||||||
variableName: 'dart2wasm',
|
variableName: 'dual-compile',
|
||||||
),
|
),
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
@ -161,7 +162,9 @@ void main() {
|
||||||
'target',
|
'target',
|
||||||
BuildInfo.debug,
|
BuildInfo.debug,
|
||||||
ServiceWorkerStrategy.offlineFirst,
|
ServiceWorkerStrategy.offlineFirst,
|
||||||
compilerConfig: const JsCompilerConfig.run(nativeNullAssertions: true),
|
compilerConfigs: <WebCompilerConfig>[
|
||||||
|
const JsCompilerConfig.run(nativeNullAssertions: true, renderer: WebRendererMode.auto),
|
||||||
|
]
|
||||||
),
|
),
|
||||||
throwsToolExit(message: 'Failed to compile application for the Web.'));
|
throwsToolExit(message: 'Failed to compile application for the Web.'));
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,7 @@ void main() {
|
||||||
<String, String>{},
|
<String, String>{},
|
||||||
<String, String>{},
|
<String, String>{},
|
||||||
NullSafetyMode.unsound,
|
NullSafetyMode.unsound,
|
||||||
|
webRenderer: WebRendererMode.canvaskit,
|
||||||
);
|
);
|
||||||
releaseAssetServer = ReleaseAssetServer(
|
releaseAssetServer = ReleaseAssetServer(
|
||||||
globals.fs.file('main.dart').uri,
|
globals.fs.file('main.dart').uri,
|
||||||
|
@ -291,6 +292,7 @@ void main() {
|
||||||
<String, String>{},
|
<String, String>{},
|
||||||
<String, String>{},
|
<String, String>{},
|
||||||
NullSafetyMode.unsound,
|
NullSafetyMode.unsound,
|
||||||
|
webRenderer: WebRendererMode.canvaskit,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(webAssetServer.basePath, 'foo/bar');
|
expect(webAssetServer.basePath, 'foo/bar');
|
||||||
|
@ -310,6 +312,7 @@ void main() {
|
||||||
<String, String>{},
|
<String, String>{},
|
||||||
<String, String>{},
|
<String, String>{},
|
||||||
NullSafetyMode.unsound,
|
NullSafetyMode.unsound,
|
||||||
|
webRenderer: WebRendererMode.canvaskit,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Defaults to "/" when there's no base element.
|
// Defaults to "/" when there's no base element.
|
||||||
|
@ -331,6 +334,7 @@ void main() {
|
||||||
<String, String>{},
|
<String, String>{},
|
||||||
<String, String>{},
|
<String, String>{},
|
||||||
NullSafetyMode.unsound,
|
NullSafetyMode.unsound,
|
||||||
|
webRenderer: WebRendererMode.canvaskit,
|
||||||
),
|
),
|
||||||
throwsToolExit(),
|
throwsToolExit(),
|
||||||
);
|
);
|
||||||
|
@ -351,6 +355,7 @@ void main() {
|
||||||
<String, String>{},
|
<String, String>{},
|
||||||
<String, String>{},
|
<String, String>{},
|
||||||
NullSafetyMode.unsound,
|
NullSafetyMode.unsound,
|
||||||
|
webRenderer: WebRendererMode.canvaskit,
|
||||||
),
|
),
|
||||||
throwsToolExit(),
|
throwsToolExit(),
|
||||||
);
|
);
|
||||||
|
@ -684,6 +689,7 @@ void main() {
|
||||||
extraHeaders: const <String, String>{},
|
extraHeaders: const <String, String>{},
|
||||||
chromiumLauncher: null,
|
chromiumLauncher: null,
|
||||||
nullSafetyMode: NullSafetyMode.unsound,
|
nullSafetyMode: NullSafetyMode.unsound,
|
||||||
|
webRenderer: WebRendererMode.html,
|
||||||
);
|
);
|
||||||
webDevFS.requireJS.createSync(recursive: true);
|
webDevFS.requireJS.createSync(recursive: true);
|
||||||
webDevFS.flutterJs.createSync(recursive: true);
|
webDevFS.flutterJs.createSync(recursive: true);
|
||||||
|
@ -745,13 +751,6 @@ void main() {
|
||||||
// New SDK should be visible..
|
// New SDK should be visible..
|
||||||
expect(await webDevFS.webAssetServer.dartSourceContents('dart_sdk.js'), 'BELLOW');
|
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.
|
// Generated entrypoint.
|
||||||
expect(await webDevFS.webAssetServer.dartSourceContents('web_entrypoint.dart'),
|
expect(await webDevFS.webAssetServer.dartSourceContents('web_entrypoint.dart'),
|
||||||
contains('GENERATED'));
|
contains('GENERATED'));
|
||||||
|
@ -800,6 +799,7 @@ void main() {
|
||||||
extraHeaders: const <String, String>{},
|
extraHeaders: const <String, String>{},
|
||||||
chromiumLauncher: null,
|
chromiumLauncher: null,
|
||||||
nullSafetyMode: NullSafetyMode.sound,
|
nullSafetyMode: NullSafetyMode.sound,
|
||||||
|
webRenderer: WebRendererMode.html,
|
||||||
);
|
);
|
||||||
webDevFS.requireJS.createSync(recursive: true);
|
webDevFS.requireJS.createSync(recursive: true);
|
||||||
webDevFS.flutterJs.createSync(recursive: true);
|
webDevFS.flutterJs.createSync(recursive: true);
|
||||||
|
@ -861,11 +861,6 @@ void main() {
|
||||||
// New SDK should be visible..
|
// New SDK should be visible..
|
||||||
expect(await webDevFS.webAssetServer.dartSourceContents('dart_sdk.js'), 'BELLOW');
|
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.
|
// Generated entrypoint.
|
||||||
expect(await webDevFS.webAssetServer.dartSourceContents('web_entrypoint.dart'),
|
expect(await webDevFS.webAssetServer.dartSourceContents('web_entrypoint.dart'),
|
||||||
contains('GENERATED'));
|
contains('GENERATED'));
|
||||||
|
@ -913,6 +908,7 @@ void main() {
|
||||||
extraHeaders: const <String, String>{},
|
extraHeaders: const <String, String>{},
|
||||||
chromiumLauncher: null,
|
chromiumLauncher: null,
|
||||||
nullSafetyMode: NullSafetyMode.sound,
|
nullSafetyMode: NullSafetyMode.sound,
|
||||||
|
webRenderer: WebRendererMode.canvaskit,
|
||||||
);
|
);
|
||||||
webDevFS.requireJS.createSync(recursive: true);
|
webDevFS.requireJS.createSync(recursive: true);
|
||||||
webDevFS.stackTraceMapper.createSync(recursive: true);
|
webDevFS.stackTraceMapper.createSync(recursive: true);
|
||||||
|
@ -974,6 +970,7 @@ void main() {
|
||||||
nullAssertions: true,
|
nullAssertions: true,
|
||||||
nativeNullAssertions: true,
|
nativeNullAssertions: true,
|
||||||
nullSafetyMode: NullSafetyMode.sound,
|
nullSafetyMode: NullSafetyMode.sound,
|
||||||
|
webRenderer: WebRendererMode.canvaskit,
|
||||||
);
|
);
|
||||||
webDevFS.requireJS.createSync(recursive: true);
|
webDevFS.requireJS.createSync(recursive: true);
|
||||||
webDevFS.stackTraceMapper.createSync(recursive: true);
|
webDevFS.stackTraceMapper.createSync(recursive: true);
|
||||||
|
@ -1019,6 +1016,7 @@ void main() {
|
||||||
extraHeaders: const <String, String>{},
|
extraHeaders: const <String, String>{},
|
||||||
chromiumLauncher: null,
|
chromiumLauncher: null,
|
||||||
nullSafetyMode: NullSafetyMode.sound,
|
nullSafetyMode: NullSafetyMode.sound,
|
||||||
|
webRenderer: WebRendererMode.canvaskit,
|
||||||
);
|
);
|
||||||
webDevFS.requireJS.createSync(recursive: true);
|
webDevFS.requireJS.createSync(recursive: true);
|
||||||
webDevFS.stackTraceMapper.createSync(recursive: true);
|
webDevFS.stackTraceMapper.createSync(recursive: true);
|
||||||
|
@ -1065,6 +1063,7 @@ void main() {
|
||||||
extraHeaders: const <String, String>{},
|
extraHeaders: const <String, String>{},
|
||||||
chromiumLauncher: null,
|
chromiumLauncher: null,
|
||||||
nullSafetyMode: NullSafetyMode.sound,
|
nullSafetyMode: NullSafetyMode.sound,
|
||||||
|
webRenderer: WebRendererMode.auto,
|
||||||
);
|
);
|
||||||
webDevFS.requireJS.createSync(recursive: true);
|
webDevFS.requireJS.createSync(recursive: true);
|
||||||
webDevFS.stackTraceMapper.createSync(recursive: true);
|
webDevFS.stackTraceMapper.createSync(recursive: true);
|
||||||
|
@ -1112,6 +1111,7 @@ void main() {
|
||||||
extraHeaders: const <String, String>{},
|
extraHeaders: const <String, String>{},
|
||||||
chromiumLauncher: null,
|
chromiumLauncher: null,
|
||||||
nullSafetyMode: NullSafetyMode.unsound,
|
nullSafetyMode: NullSafetyMode.unsound,
|
||||||
|
webRenderer: WebRendererMode.canvaskit,
|
||||||
);
|
);
|
||||||
webDevFS.requireJS.createSync(recursive: true);
|
webDevFS.requireJS.createSync(recursive: true);
|
||||||
webDevFS.stackTraceMapper.createSync(recursive: true);
|
webDevFS.stackTraceMapper.createSync(recursive: true);
|
||||||
|
@ -1148,7 +1148,9 @@ void main() {
|
||||||
null,
|
null,
|
||||||
const <String, String>{},
|
const <String, String>{},
|
||||||
NullSafetyMode.unsound,
|
NullSafetyMode.unsound,
|
||||||
testMode: true);
|
webRenderer: WebRendererMode.canvaskit,
|
||||||
|
testMode: true
|
||||||
|
);
|
||||||
|
|
||||||
expect(webAssetServer.defaultResponseHeaders['x-frame-options'], null);
|
expect(webAssetServer.defaultResponseHeaders['x-frame-options'], null);
|
||||||
await webAssetServer.dispose();
|
await webAssetServer.dispose();
|
||||||
|
@ -1180,7 +1182,9 @@ void main() {
|
||||||
extraHeaderKey: extraHeaderValue,
|
extraHeaderKey: extraHeaderValue,
|
||||||
},
|
},
|
||||||
NullSafetyMode.unsound,
|
NullSafetyMode.unsound,
|
||||||
testMode: true);
|
webRenderer: WebRendererMode.canvaskit,
|
||||||
|
testMode: true
|
||||||
|
);
|
||||||
|
|
||||||
expect(webAssetServer.defaultResponseHeaders[extraHeaderKey], <String>[extraHeaderValue]);
|
expect(webAssetServer.defaultResponseHeaders[extraHeaderKey], <String>[extraHeaderValue]);
|
||||||
|
|
||||||
|
@ -1215,6 +1219,7 @@ void main() {
|
||||||
<String, String>{},
|
<String, String>{},
|
||||||
<String, String>{},
|
<String, String>{},
|
||||||
NullSafetyMode.sound,
|
NullSafetyMode.sound,
|
||||||
|
webRenderer: WebRendererMode.canvaskit,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(await webAssetServer.metadataContents('foo/main_module.ddc_merged_metadata'), null);
|
expect(await webAssetServer.metadataContents('foo/main_module.ddc_merged_metadata'), null);
|
||||||
|
@ -1257,6 +1262,7 @@ void main() {
|
||||||
extraHeaders: const <String, String>{},
|
extraHeaders: const <String, String>{},
|
||||||
chromiumLauncher: null,
|
chromiumLauncher: null,
|
||||||
nullSafetyMode: NullSafetyMode.unsound,
|
nullSafetyMode: NullSafetyMode.unsound,
|
||||||
|
webRenderer: WebRendererMode.canvaskit,
|
||||||
);
|
);
|
||||||
webDevFS.requireJS.createSync(recursive: true);
|
webDevFS.requireJS.createSync(recursive: true);
|
||||||
webDevFS.stackTraceMapper.createSync(recursive: true);
|
webDevFS.stackTraceMapper.createSync(recursive: true);
|
||||||
|
|
|
@ -51,7 +51,7 @@ void main() {
|
||||||
final Directory appBuildDir = fileSystem.directory(fileSystem.path.join(
|
final Directory appBuildDir = fileSystem.directory(fileSystem.path.join(
|
||||||
exampleAppDir.path,
|
exampleAppDir.path,
|
||||||
'build',
|
'build',
|
||||||
'web_wasm',
|
'web',
|
||||||
));
|
));
|
||||||
for (final String filename in const <String>[
|
for (final String filename in const <String>[
|
||||||
'flutter.js',
|
'flutter.js',
|
||||||
|
|
|
@ -19,6 +19,7 @@ void main() async {
|
||||||
await _testProject(HotReloadProject(indexHtml: indexHtmlFlutterJsCallback), name: 'flutter.js (callback)');
|
await _testProject(HotReloadProject(indexHtml: indexHtmlFlutterJsCallback), name: 'flutter.js (callback)');
|
||||||
await _testProject(HotReloadProject(indexHtml: indexHtmlFlutterJsPromisesFull), name: 'flutter.js (promises)');
|
await _testProject(HotReloadProject(indexHtml: indexHtmlFlutterJsPromisesFull), name: 'flutter.js (promises)');
|
||||||
await _testProject(HotReloadProject(indexHtml: indexHtmlFlutterJsPromisesShort), name: 'flutter.js (promises, short)');
|
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');
|
await _testProject(HotReloadProject(indexHtml: indexHtmlNoFlutterJs), name: 'No flutter.js');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,27 @@ 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
|
/// index_without_flutterjs.html
|
||||||
String indexHtmlNoFlutterJs = '''
|
String indexHtmlNoFlutterJs = '''
|
||||||
<!DOCTYPE HTML>
|
<!DOCTYPE HTML>
|
||||||
|
|
Loading…
Reference in a new issue