Adding support for DDC modules when running Flutter Web in debug mode (#141423)

### Context:

DDC modules are abstractions over how libraries are loaded/updated. The entirety of google3 uses the DDC/legacy module system due to its flexibility extensibility over the other two (ES6 and AMD/RequireJS). Unifying DDC's module system saves us from duplicating work and will allow us to have finer grained control over how JS modules are loaded. This is a a prerequisite to features such as hot reload.

### Overview:

This change plumbs a boolean flag through flutter_tools that switches between DDC (new) and AMD (current) modules. This mode is automatically applied when `--extra-front-end-options=--dartdevc-module-format=ddc` is specified alongside `flutter run`. Other important additions include:
* Splitting Flutter artifacts between DDC and AMD modules
* Adding unit tests for the DDC module system
* Additional bootstrapper logic for the DDC module system

We don't expect to see any user-visible behavior or performance differences.

This is dependent on [incoming module system support in DWDS](https://github.com/dart-lang/webdev/pull/2295) and [additional artifacts in the engine](https://github.com/flutter/engine/pull/47783).

This is part of a greater effort to deprecate the AMD module system: https://github.com/dart-lang/sdk/issues/52361
This commit is contained in:
MarkZ 2024-02-23 16:26:04 -08:00 committed by GitHub
parent b781da9b58
commit ee94fe262b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 2458 additions and 135 deletions

View file

@ -94,19 +94,34 @@ enum HostArtifact {
/// The summary dill with null safety enabled for the dartdevc target.
webPlatformDart2JSSoundKernelDill,
/// The precompiled SDKs and sourcemaps for web debug builds.
webPrecompiledSdk,
webPrecompiledSdkSourcemaps,
webPrecompiledCanvaskitSdk,
webPrecompiledCanvaskitSdkSourcemaps,
webPrecompiledCanvaskitAndHtmlSdk,
webPrecompiledCanvaskitAndHtmlSdkSourcemaps,
webPrecompiledSoundSdk,
webPrecompiledSoundSdkSourcemaps,
webPrecompiledCanvaskitSoundSdk,
webPrecompiledCanvaskitSoundSdkSourcemaps,
webPrecompiledCanvaskitAndHtmlSoundSdk,
webPrecompiledCanvaskitAndHtmlSoundSdkSourcemaps,
/// The precompiled SDKs and sourcemaps for web debug builds with the AMD module system.
// TODO(markzipan): delete these when DDC's AMD module system is deprecated, https://github.com/flutter/flutter/issues/142060.
webPrecompiledAmdSdk,
webPrecompiledAmdSdkSourcemaps,
webPrecompiledAmdCanvaskitSdk,
webPrecompiledAmdCanvaskitSdkSourcemaps,
webPrecompiledAmdCanvaskitAndHtmlSdk,
webPrecompiledAmdCanvaskitAndHtmlSdkSourcemaps,
webPrecompiledAmdSoundSdk,
webPrecompiledAmdSoundSdkSourcemaps,
webPrecompiledAmdCanvaskitSoundSdk,
webPrecompiledAmdCanvaskitSoundSdkSourcemaps,
webPrecompiledAmdCanvaskitAndHtmlSoundSdk,
webPrecompiledAmdCanvaskitAndHtmlSoundSdkSourcemaps,
/// The precompiled SDKs and sourcemaps for web debug builds with the DDC module system.
webPrecompiledDdcSdk,
webPrecompiledDdcSdkSourcemaps,
webPrecompiledDdcCanvaskitSdk,
webPrecompiledDdcCanvaskitSdkSourcemaps,
webPrecompiledDdcCanvaskitAndHtmlSdk,
webPrecompiledDdcCanvaskitAndHtmlSdkSourcemaps,
webPrecompiledDdcSoundSdk,
webPrecompiledDdcSoundSdkSourcemaps,
webPrecompiledDdcCanvaskitSoundSdk,
webPrecompiledDdcCanvaskitSoundSdkSourcemaps,
webPrecompiledDdcCanvaskitAndHtmlSoundSdk,
webPrecompiledDdcCanvaskitAndHtmlSoundSdkSourcemaps,
iosDeploy,
idevicesyslog,
@ -256,19 +271,31 @@ String _hostArtifactToFileName(HostArtifact artifact, Platform platform) {
return 'dart2js_platform.dill';
case HostArtifact.flutterWebLibrariesJson:
return 'libraries.json';
case HostArtifact.webPrecompiledSdk:
case HostArtifact.webPrecompiledCanvaskitSdk:
case HostArtifact.webPrecompiledCanvaskitAndHtmlSdk:
case HostArtifact.webPrecompiledSoundSdk:
case HostArtifact.webPrecompiledCanvaskitSoundSdk:
case HostArtifact.webPrecompiledCanvaskitAndHtmlSoundSdk:
case HostArtifact.webPrecompiledAmdSdk:
case HostArtifact.webPrecompiledAmdCanvaskitSdk:
case HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSdk:
case HostArtifact.webPrecompiledAmdSoundSdk:
case HostArtifact.webPrecompiledAmdCanvaskitSoundSdk:
case HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSoundSdk:
case HostArtifact.webPrecompiledDdcSdk:
case HostArtifact.webPrecompiledDdcCanvaskitSdk:
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdk:
case HostArtifact.webPrecompiledDdcSoundSdk:
case HostArtifact.webPrecompiledDdcCanvaskitSoundSdk:
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSoundSdk:
return 'dart_sdk.js';
case HostArtifact.webPrecompiledSdkSourcemaps:
case HostArtifact.webPrecompiledCanvaskitSdkSourcemaps:
case HostArtifact.webPrecompiledCanvaskitAndHtmlSdkSourcemaps:
case HostArtifact.webPrecompiledSoundSdkSourcemaps:
case HostArtifact.webPrecompiledCanvaskitSoundSdkSourcemaps:
case HostArtifact.webPrecompiledCanvaskitAndHtmlSoundSdkSourcemaps:
case HostArtifact.webPrecompiledAmdSdkSourcemaps:
case HostArtifact.webPrecompiledAmdCanvaskitSdkSourcemaps:
case HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSdkSourcemaps:
case HostArtifact.webPrecompiledAmdSoundSdkSourcemaps:
case HostArtifact.webPrecompiledAmdCanvaskitSoundSdkSourcemaps:
case HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSoundSdkSourcemaps:
case HostArtifact.webPrecompiledDdcSdkSourcemaps:
case HostArtifact.webPrecompiledDdcCanvaskitSdkSourcemaps:
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdkSourcemaps:
case HostArtifact.webPrecompiledDdcSoundSdkSourcemaps:
case HostArtifact.webPrecompiledDdcCanvaskitSoundSdkSourcemaps:
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSoundSdkSourcemaps:
return 'dart_sdk.js.map';
case HostArtifact.impellerc:
return 'impellerc$exe';
@ -454,30 +481,54 @@ class CachedArtifacts implements Artifacts {
case HostArtifact.webPlatformDart2JSSoundKernelDill:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledSdk:
case HostArtifact.webPrecompiledSdkSourcemaps:
case HostArtifact.webPrecompiledAmdSdk:
case HostArtifact.webPrecompiledAmdSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitSdk:
case HostArtifact.webPrecompiledCanvaskitSdkSourcemaps:
case HostArtifact.webPrecompiledAmdCanvaskitSdk:
case HostArtifact.webPrecompiledAmdCanvaskitSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitAndHtmlSdk:
case HostArtifact.webPrecompiledCanvaskitAndHtmlSdkSourcemaps:
case HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSdk:
case HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit-html', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledSoundSdk:
case HostArtifact.webPrecompiledSoundSdkSourcemaps:
case HostArtifact.webPrecompiledAmdSoundSdk:
case HostArtifact.webPrecompiledAmdSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitSoundSdk:
case HostArtifact.webPrecompiledCanvaskitSoundSdkSourcemaps:
case HostArtifact.webPrecompiledAmdCanvaskitSoundSdk:
case HostArtifact.webPrecompiledAmdCanvaskitSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitAndHtmlSoundSdk:
case HostArtifact.webPrecompiledCanvaskitAndHtmlSoundSdkSourcemaps:
case HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSoundSdk:
case HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit-html-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcSdk:
case HostArtifact.webPrecompiledDdcSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'ddc', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcCanvaskitSdk:
case HostArtifact.webPrecompiledDdcCanvaskitSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'ddc-canvaskit', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdk:
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'ddc-canvaskit-html', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcSoundSdk:
case HostArtifact.webPrecompiledDdcSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'ddc-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcCanvaskitSoundSdk:
case HostArtifact.webPrecompiledDdcCanvaskitSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'ddc-canvaskit-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSoundSdk:
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'ddc-canvaskit-html-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.idevicesyslog:
case HostArtifact.idevicescreenshot:
final String artifactFileName = _hostArtifactToFileName(artifact, _platform);
@ -886,7 +937,9 @@ class CachedLocalEngineArtifacts implements Artifacts {
final Artifacts _backupCache;
@override
FileSystemEntity getHostArtifact(HostArtifact artifact) {
FileSystemEntity getHostArtifact(
HostArtifact artifact,
) {
switch (artifact) {
case HostArtifact.flutterWebSdk:
final String path = _getFlutterWebSdkPath();
@ -906,30 +959,54 @@ class CachedLocalEngineArtifacts implements Artifacts {
case HostArtifact.webPlatformDart2JSSoundKernelDill:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledSdk:
case HostArtifact.webPrecompiledSdkSourcemaps:
case HostArtifact.webPrecompiledAmdSdk:
case HostArtifact.webPrecompiledAmdSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitSdk:
case HostArtifact.webPrecompiledCanvaskitSdkSourcemaps:
case HostArtifact.webPrecompiledAmdCanvaskitSdk:
case HostArtifact.webPrecompiledAmdCanvaskitSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitAndHtmlSdk:
case HostArtifact.webPrecompiledCanvaskitAndHtmlSdkSourcemaps:
case HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSdk:
case HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit-html', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledSoundSdk:
case HostArtifact.webPrecompiledSoundSdkSourcemaps:
case HostArtifact.webPrecompiledAmdSoundSdk:
case HostArtifact.webPrecompiledAmdSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitSoundSdk:
case HostArtifact.webPrecompiledCanvaskitSoundSdkSourcemaps:
case HostArtifact.webPrecompiledAmdCanvaskitSoundSdk:
case HostArtifact.webPrecompiledAmdCanvaskitSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitAndHtmlSoundSdk:
case HostArtifact.webPrecompiledCanvaskitAndHtmlSoundSdkSourcemaps:
case HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSoundSdk:
case HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit-html-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcSdk:
case HostArtifact.webPrecompiledDdcSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'ddc', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcCanvaskitSdk:
case HostArtifact.webPrecompiledDdcCanvaskitSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'ddc-canvaskit', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdk:
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'ddc-canvaskit-html', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcSoundSdk:
case HostArtifact.webPrecompiledDdcSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'ddc-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcCanvaskitSoundSdk:
case HostArtifact.webPrecompiledDdcCanvaskitSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'ddc-canvaskit-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSoundSdk:
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'ddc-canvaskit-html-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.idevicesyslog:
case HostArtifact.idevicescreenshot:
final String artifactFileName = _hostArtifactToFileName(artifact, _platform);
@ -1196,7 +1273,9 @@ class CachedLocalWebSdkArtifacts implements Artifacts {
String getEngineType(TargetPlatform platform, [BuildMode? mode]) => _parent.getEngineType(platform, mode);
@override
FileSystemEntity getHostArtifact(HostArtifact artifact) {
FileSystemEntity getHostArtifact(
HostArtifact artifact,
) {
switch (artifact) {
case HostArtifact.flutterWebSdk:
final String path = _getFlutterWebSdkPath();
@ -1216,30 +1295,54 @@ class CachedLocalWebSdkArtifacts implements Artifacts {
case HostArtifact.webPlatformDart2JSSoundKernelDill:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledSdk:
case HostArtifact.webPrecompiledSdkSourcemaps:
case HostArtifact.webPrecompiledAmdSdk:
case HostArtifact.webPrecompiledAmdSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitSdk:
case HostArtifact.webPrecompiledCanvaskitSdkSourcemaps:
case HostArtifact.webPrecompiledAmdCanvaskitSdk:
case HostArtifact.webPrecompiledAmdCanvaskitSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitAndHtmlSdk:
case HostArtifact.webPrecompiledCanvaskitAndHtmlSdkSourcemaps:
case HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSdk:
case HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit-html', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledSoundSdk:
case HostArtifact.webPrecompiledSoundSdkSourcemaps:
case HostArtifact.webPrecompiledAmdSoundSdk:
case HostArtifact.webPrecompiledAmdSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitSoundSdk:
case HostArtifact.webPrecompiledCanvaskitSoundSdkSourcemaps:
case HostArtifact.webPrecompiledAmdCanvaskitSoundSdk:
case HostArtifact.webPrecompiledAmdCanvaskitSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitAndHtmlSoundSdk:
case HostArtifact.webPrecompiledCanvaskitAndHtmlSoundSdkSourcemaps:
case HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSoundSdk:
case HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit-html-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcSdk:
case HostArtifact.webPrecompiledDdcSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'ddc', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcCanvaskitSdk:
case HostArtifact.webPrecompiledDdcCanvaskitSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'ddc-canvaskit', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdk:
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'ddc-canvaskit-html', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcSoundSdk:
case HostArtifact.webPrecompiledDdcSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'ddc-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcCanvaskitSoundSdk:
case HostArtifact.webPrecompiledDdcCanvaskitSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'ddc-canvaskit-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSoundSdk:
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'ddc-canvaskit-html-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.iosDeploy:
case HostArtifact.idevicesyslog:
case HostArtifact.idevicescreenshot:

View file

@ -222,6 +222,10 @@ class BuildInfo {
/// so the uncapitalized flavor name is used to compute the output file name
String? get uncapitalizedFlavor => _uncapitalize(flavor);
/// The module system DDC is targeting, or null if not using DDC.
// TODO(markzipan): delete this when DDC's AMD module system is deprecated, https://github.com/flutter/flutter/issues/142060.
DdcModuleFormat? get ddcModuleFormat => _ddcModuleFormatFromFrontEndArgs(extraFrontEndOptions);
/// Convert to a structured string encoded structure appropriate for usage
/// in build system [Environment.defines].
///
@ -1044,6 +1048,28 @@ enum NullSafetyMode {
autodetect,
}
/// Indicates the module system DDC is targeting.
enum DdcModuleFormat {
amd,
ddc,
}
// TODO(markzipan): delete this when DDC's AMD module system is deprecated, https://github.com/flutter/flutter/issues/142060.
DdcModuleFormat? _ddcModuleFormatFromFrontEndArgs(List<String>? extraFrontEndArgs) {
if (extraFrontEndArgs == null) {
return null;
}
const String ddcModuleFormatString = '--dartdevc-module-format=';
for (final String flag in extraFrontEndArgs) {
if (flag.startsWith(ddcModuleFormatString)) {
final String moduleFormatString = flag
.substring(ddcModuleFormatString.length, flag.length);
return DdcModuleFormat.values.byName(moduleFormatString);
}
}
return null;
}
String _getCurrentHostPlatformArchName() {
final HostPlatform hostPlatform = getCurrentHostPlatform();
return hostPlatform.platformName;

View file

@ -117,7 +117,8 @@ class WebAssetServer implements AssetReader {
this.internetAddress,
this._modules,
this._digests,
this._nullSafetyMode, {
this._nullSafetyMode,
this._ddcModuleSystem, {
required this.webRenderer,
}) : basePath = _getIndexHtml().getBaseHref();
@ -181,6 +182,8 @@ class WebAssetServer implements AssetReader {
required WebRendererMode webRenderer,
bool testMode = false,
DwdsLauncher dwdsLauncher = Dwds.start,
// TODO(markzipan): Make sure this default value aligns with that in the debugger options.
bool ddcModuleSystem = false,
}) async {
InternetAddress address;
if (hostname == 'any') {
@ -227,6 +230,7 @@ class WebAssetServer implements AssetReader {
modules,
digests,
nullSafetyMode,
ddcModuleSystem,
webRenderer: webRenderer,
);
if (testMode) {
@ -285,7 +289,8 @@ class WebAssetServer implements AssetReader {
return chromium.chromeConnection;
},
toolConfiguration: ToolConfiguration(
loadStrategy: FrontendServerRequireStrategyProvider(
loadStrategy: ddcModuleSystem
? FrontendServerLegacyStrategyProvider(
ReloadConfiguration.none,
server,
PackageUriMapper(packageConfig),
@ -293,8 +298,17 @@ class WebAssetServer implements AssetReader {
BuildSettings(
appEntrypoint: packageConfig.toPackageUri(
globals.fs.file(entrypoint).absolute.uri,
),
),
)),
).strategy
: FrontendServerRequireStrategyProvider(
ReloadConfiguration.none,
server,
PackageUriMapper(packageConfig),
digestProvider,
BuildSettings(
appEntrypoint: packageConfig.toPackageUri(
globals.fs.file(entrypoint).absolute.uri,
)),
).strategy,
debugSettings: DebugSettings(
enableDebugExtension: true,
@ -328,6 +342,7 @@ class WebAssetServer implements AssetReader {
}
final NullSafetyMode _nullSafetyMode;
final bool _ddcModuleSystem;
final HttpServer _httpServer;
final WebMemoryFS _webMemoryFS = WebMemoryFS();
final PackageConfig _packages;
@ -510,9 +525,7 @@ class WebAssetServer implements AssetReader {
final WebRendererMode webRenderer;
shelf.Response _serveIndex() {
final IndexHtml indexHtml = _getIndexHtml();
final Map<String, dynamic> buildConfig = <String, dynamic>{
'engineRevision': globals.flutterVersion.engineRevision,
'builds': <dynamic>[
@ -597,15 +610,22 @@ class WebAssetServer implements AssetReader {
return webSdkFile;
}
File get _resolveDartSdkJsFile =>
globals.fs.file(globals.artifacts!.getHostArtifact(
kDartSdkJsArtifactMap[webRenderer]![_nullSafetyMode]!
));
File get _resolveDartSdkJsFile {
final Map<WebRendererMode, Map<NullSafetyMode, HostArtifact>>
dartSdkArtifactMap =
_ddcModuleSystem ? kDdcDartSdkJsArtifactMap : kAmdDartSdkJsArtifactMap;
return globals.fs.file(globals.artifacts!
.getHostArtifact(dartSdkArtifactMap[webRenderer]![_nullSafetyMode]!));
}
File get _resolveDartSdkJsMapFile =>
globals.fs.file(globals.artifacts!.getHostArtifact(
kDartSdkJsMapArtifactMap[webRenderer]![_nullSafetyMode]!
));
File get _resolveDartSdkJsMapFile {
final Map<WebRendererMode, Map<NullSafetyMode, HostArtifact>>
dartSdkArtifactMap = _ddcModuleSystem
? kDdcDartSdkJsMapArtifactMap
: kAmdDartSdkJsMapArtifactMap;
return globals.fs.file(globals.artifacts!
.getHostArtifact(dartSdkArtifactMap[webRenderer]![_nullSafetyMode]!));
}
@override
Future<String?> dartSourceContents(String serverPath) async {
@ -679,6 +699,7 @@ class WebDevFS implements DevFS {
required this.nullAssertions,
required this.nativeNullAssertions,
required this.nullSafetyMode,
required this.ddcModuleSystem,
required this.webRenderer,
this.testMode = false,
}) : _port = port;
@ -695,6 +716,7 @@ class WebDevFS implements DevFS {
final bool enableDds;
final Map<String, String> extraHeaders;
final bool testMode;
final bool ddcModuleSystem;
final ExpressionCompiler? expressionCompiler;
final ChromiumLauncher? chromiumLauncher;
final bool nullAssertions;
@ -805,15 +827,16 @@ class WebDevFS implements DevFS {
nullSafetyMode,
webRenderer: webRenderer,
testMode: testMode,
ddcModuleSystem: ddcModuleSystem,
);
final int selectedPort = webAssetServer.selectedPort;
String url = '$hostname:$selectedPort';
if (hostname == 'any') {
url ='localhost:$selectedPort';
url = 'localhost:$selectedPort';
}
_baseUri = Uri.http(url, webAssetServer.basePath);
if (tlsCertPath != null && tlsCertKeyPath!= null) {
if (tlsCertPath != null && tlsCertKeyPath != null) {
_baseUri = Uri.https(url, webAssetServer.basePath);
}
return _baseUri!;
@ -866,7 +889,12 @@ class WebDevFS implements DevFS {
generator.addFileSystemRoot(outputDirectoryPath);
final String entrypoint = globals.fs.path.basename(mainFile.path);
webAssetServer.writeBytes(entrypoint, mainFile.readAsBytesSync());
webAssetServer.writeBytes('require.js', requireJS.readAsBytesSync());
if (ddcModuleSystem) {
webAssetServer.writeBytes(
'ddc_module_loader.js', ddcModuleLoaderJS.readAsBytesSync());
} else {
webAssetServer.writeBytes('require.js', requireJS.readAsBytesSync());
}
webAssetServer.writeBytes('flutter.js', flutterJs.readAsBytesSync());
webAssetServer.writeBytes(
'stack_trace_mapper.js', stackTraceMapper.readAsBytesSync());
@ -878,7 +906,14 @@ class WebDevFS implements DevFS {
'version.json', FlutterProject.current().getVersionInfo());
webAssetServer.writeFile(
'main.dart.js',
generateBootstrapScript(
ddcModuleSystem
? generateDDCBootstrapScript(
entrypoint: entrypoint,
ddcModuleLoaderUrl: 'ddc_module_loader.js',
mapperUrl: 'stack_trace_mapper.js',
generateLoadingIndicator: enableDwds,
)
: generateBootstrapScript(
requireUrl: 'require.js',
mapperUrl: 'stack_trace_mapper.js',
generateLoadingIndicator: enableDwds,
@ -886,7 +921,14 @@ class WebDevFS implements DevFS {
);
webAssetServer.writeFile(
'main_module.bootstrap.js',
generateMainModule(
ddcModuleSystem
? generateDDCMainModule(
entrypoint: entrypoint,
nullAssertions: nullAssertions,
nativeNullAssertions: nativeNullAssertions,
exportedMain: pathToJSIdentifier(entrypoint.split('.')[0]),
)
: generateMainModule(
entrypoint: entrypoint,
nullAssertions: nullAssertions,
nativeNullAssertions: nativeNullAssertions,
@ -968,6 +1010,16 @@ class WebDevFS implements DevFS {
'require.js',
));
@visibleForTesting
final File ddcModuleLoaderJS = globals.fs.file(globals.fs.path.join(
globals.artifacts!.getArtifactPath(Artifact.engineDartSdkPath,
platform: TargetPlatform.web_javascript),
'lib',
'dev_compiler',
'ddc',
'ddc_module_loader.js',
));
@visibleForTesting
final File flutterJs = globals.fs.file(globals.fs.path.join(
globals.artifacts!.getHostArtifact(HostArtifact.flutterJsDirectory).path,

View file

@ -166,11 +166,12 @@ class ResidentWebRunner extends ResidentRunner {
if (_instance != null) {
return _instance!;
}
final vmservice.VmService? service =_connectionResult?.vmService;
final vmservice.VmService? service = _connectionResult?.vmService;
final Uri websocketUri = Uri.parse(_connectionResult!.debugConnection!.uri);
final Uri httpUri = _httpUriFromWebsocketUri(websocketUri);
return _instance ??= FlutterVmService(service!, wsAddress: websocketUri, httpAddress: httpUri);
}
FlutterVmService? _instance;
@override
@ -289,6 +290,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
debuggingOptions.webEnableExpressionEvaluation
? WebExpressionCompiler(device!.generator!, fileSystem: _fileSystem)
: null;
device!.devFS = WebDevFS(
hostname: debuggingOptions.hostname ?? 'localhost',
port: await getPort(),
@ -309,6 +311,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
nullAssertions: debuggingOptions.nullAssertions,
nullSafetyMode: debuggingOptions.buildInfo.nullSafetyMode,
nativeNullAssertions: debuggingOptions.nativeNullAssertions,
ddcModuleSystem: debuggingOptions.buildInfo.ddcModuleFormat == DdcModuleFormat.ddc,
webRenderer: debuggingOptions.webRenderer,
);
Uri url = await device!.devFS!.create();
@ -605,7 +608,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
_connectionResult = await webDevFS.connect(useDebugExtension);
unawaited(_connectionResult!.debugConnection!.onDone.whenComplete(_cleanupAndExit));
void onLogEvent(vmservice.Event event) {
void onLogEvent(vmservice.Event event) {
final String message = processVmServiceMessage(event);
_logger.printStatus(message);
}
@ -640,7 +643,6 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
vmService: _vmService.service,
);
websocketUri = Uri.parse(_connectionResult!.debugConnection!.uri);
device!.vmService = _vmService;
@ -651,8 +653,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
_connectionResult!.appConnection!.runMain();
} else {
late StreamSubscription<void> resumeSub;
resumeSub = _vmService.service.onDebugEvent
.listen((vmservice.Event event) {
resumeSub = _vmService.service.onDebugEvent.listen((vmservice.Event event) {
if (event.type == vmservice.EventKind.kResume) {
_connectionResult!.appConnection!.runMain();
resumeSub.cancel();
@ -674,7 +675,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
..writeAsStringSync(websocketUri.toString());
}
_logger.printStatus('Debug service listening on $websocketUri');
if (debuggingOptions.buildInfo.nullSafetyMode != NullSafetyMode.sound) {
if (debuggingOptions.buildInfo.nullSafetyMode != NullSafetyMode.sound) {
_logger.printStatus('');
_logger.printStatus(
'Running without sound null safety ⚠️',

View file

@ -236,6 +236,15 @@ class FlutterWebPlatform extends PlatformPlugin {
'require.js',
));
/// The ddc module loader js binary.
File get _ddcModuleLoaderJs => _fileSystem.file(_fileSystem.path.join(
_artifacts!.getArtifactPath(Artifact.engineDartSdkPath, platform: TargetPlatform.web_javascript),
'lib',
'dev_compiler',
'ddc',
'ddc_module_loader.js',
));
/// The ddc to dart stack trace mapper.
File get _stackTraceMapper => _fileSystem.file(_fileSystem.path.join(
_artifacts!.getArtifactPath(Artifact.engineDartSdkPath, platform: TargetPlatform.web_javascript),
@ -245,11 +254,15 @@ class FlutterWebPlatform extends PlatformPlugin {
'dart_stack_trace_mapper.js',
));
File get _dartSdk => _fileSystem.file(
_artifacts!.getHostArtifact(kDartSdkJsArtifactMap[webRenderer]![_nullSafetyMode]!));
File get _dartSdk {
final Map<WebRendererMode, Map<NullSafetyMode, HostArtifact>> dartSdkArtifactMap = buildInfo.ddcModuleFormat == DdcModuleFormat.ddc ? kDdcDartSdkJsArtifactMap : kAmdDartSdkJsArtifactMap;
return _fileSystem.file(_artifacts!.getHostArtifact(dartSdkArtifactMap[webRenderer]![_nullSafetyMode]!));
}
File get _dartSdkSourcemaps => _fileSystem.file(
_artifacts!.getHostArtifact(kDartSdkJsMapArtifactMap[webRenderer]![_nullSafetyMode]!));
File get _dartSdkSourcemaps {
final Map<WebRendererMode, Map<NullSafetyMode, HostArtifact>> dartSdkArtifactMap = buildInfo.ddcModuleFormat == DdcModuleFormat.ddc ? kDdcDartSdkJsMapArtifactMap : kAmdDartSdkJsMapArtifactMap;
return _fileSystem.file(_artifacts!.getHostArtifact(dartSdkArtifactMap[webRenderer]![_nullSafetyMode]!));
}
File _canvasKitFile(String relativePath) {
final String canvasKitPath = _fileSystem.path.join(
@ -303,6 +316,11 @@ class FlutterWebPlatform extends PlatformPlugin {
_requireJs.openRead(),
headers: <String, String>{'Content-Type': 'text/javascript'},
);
} else if (request.requestedUri.path.contains('ddc_module_loader.js')) {
return shelf.Response.ok(
_ddcModuleLoaderJs.openRead(),
headers: <String, String>{'Content-Type': 'text/javascript'},
);
} else if (request.requestedUri.path.contains('ahem.ttf')) {
return shelf.Response.ok(_ahem.openRead());
} else if (request.requestedUri.path.contains('dart_sdk.js')) {

View file

@ -4,6 +4,136 @@
import 'package:package_config/package_config.dart';
String generateDDCBootstrapScript({
required String entrypoint,
required String ddcModuleLoaderUrl,
required String mapperUrl,
required bool generateLoadingIndicator,
String appRootDirectory = '/',
}) {
return '''
${generateLoadingIndicator ? _generateLoadingIndicator() : ""}
// TODO(markzipan): This is safe if Flutter app roots are always equal to the
// host root '/'. Validate if this is true.
var _currentDirectory = "$appRootDirectory";
window.\$dartCreateScript = (function() {
// Find the nonce value. (Note, this is only computed once.)
var scripts = Array.from(document.getElementsByTagName("script"));
var nonce;
scripts.some(
script => (nonce = script.nonce || script.getAttribute("nonce")));
// If present, return a closure that automatically appends the nonce.
if (nonce) {
return function() {
var script = document.createElement("script");
script.nonce = nonce;
return script;
};
} else {
return function() {
return document.createElement("script");
};
}
})();
// Loads a module [relativeUrl] relative to [root].
//
// If not specified, [root] defaults to the directory serving the main app.
var forceLoadModule = function (relativeUrl, root) {
var actualRoot = root ?? _currentDirectory;
return new Promise(function(resolve, reject) {
var script = self.\$dartCreateScript();
let policy = {
createScriptURL: function(src) {return src;}
};
if (self.trustedTypes && self.trustedTypes.createPolicy) {
policy = self.trustedTypes.createPolicy('dartDdcModuleUrl', policy);
}
script.onload = resolve;
script.onerror = reject;
script.src = policy.createScriptURL(actualRoot + relativeUrl);
document.head.appendChild(script);
});
};
// A map containing the URLs for the bootstrap scripts in debug.
let _scriptUrls = {
"mapper": "$mapperUrl",
"moduleLoader": "$ddcModuleLoaderUrl"
};
(function() {
let appName = "$entrypoint";
// A uuid that identifies a subapp.
// Stubbed out since subapps aren't supported in Flutter.
let uuid = "00000000-0000-0000-0000-000000000000";
window.postMessage(
{type: "DDC_STATE_CHANGE", state: "initial_load", targetUuid: uuid}, "*");
// Load pre-requisite DDC scripts.
// We intentionally use invalid names to avoid namespace clashes.
let prerequisiteScripts = [
{
"src": "$ddcModuleLoaderUrl",
"id": "ddc_module_loader \x00"
},
{
"src": "$mapperUrl",
"id": "dart_stack_trace_mapper \x00"
}
];
// Load ddc_module_loader.js to access DDC's module loader API.
let prerequisiteLoads = [];
for (let i = 0; i < prerequisiteScripts.length; i++) {
prerequisiteLoads.push(forceLoadModule(prerequisiteScripts[i].src));
}
Promise.all(prerequisiteLoads).then((_) => afterPrerequisiteLogic());
// Save the current script so we can access it in a closure.
var _currentScript = document.currentScript;
var afterPrerequisiteLogic = function() {
window.\$dartLoader.rootDirectories.push(_currentDirectory);
let scripts = [
{
"src": "dart_sdk.js",
"id": "dart_sdk"
},
{
"src": "main_module.bootstrap.js",
"id": "data-main"
}
];
let loadConfig = new window.\$dartLoader.LoadConfiguration();
loadConfig.bootstrapScript = scripts[scripts.length - 1];
loadConfig.loadScriptFn = function(loader) {
loader.addScriptsToQueue(scripts, null);
loader.loadEnqueuedModules();
}
loadConfig.ddcEventForLoadStart = /* LOAD_ALL_MODULES_START */ 1;
loadConfig.ddcEventForLoadedOk = /* LOAD_ALL_MODULES_END_OK */ 2;
loadConfig.ddcEventForLoadedError = /* LOAD_ALL_MODULES_END_ERROR */ 3;
let loader = new window.\$dartLoader.DDCLoader(loadConfig);
// Record prerequisite scripts' fully resolved URLs.
prerequisiteScripts.forEach(script => loader.registerScript(script));
// Note: these variables should only be used in non-multi-app scenarios since
// they can be arbitrarily overridden based on multi-app load order.
window.\$dartLoader.loadConfig = loadConfig;
window.\$dartLoader.loader = loader;
loader.nextAttempt();
}
})();
''';
}
/// The JavaScript bootstrap script to support in-browser hot restart.
///
/// The [requireUrl] loads our cached RequireJS script file. The [mapperUrl]
@ -157,6 +287,39 @@ document.addEventListener('dart-app-ready', function (e) {
''';
}
String generateDDCMainModule({
required String entrypoint,
required bool nullAssertions,
required bool nativeNullAssertions,
String? exportedMain,
}) {
final String entrypointMainName = exportedMain ?? entrypoint.split('.')[0];
// The typo below in "EXTENTION" is load-bearing, package:build depends on it.
return '''
/* ENTRYPOINT_EXTENTION_MARKER */
(function() {
// Flutter Web uses a generated main entrypoint, which shares app and module names.
let appName = "$entrypoint";
let moduleName = "$entrypoint";
// Use a dummy UUID since multi-apps are not supported on Flutter Web.
let uuid = "00000000-0000-0000-0000-000000000000";
let child = {};
child.main = function() {
let dart = self.dart_library.import('dart_sdk', appName).dart;
dart.nonNullAsserts($nullAssertions);
dart.nativeNonNullAsserts($nativeNullAssertions);
self.dart_library.start(appName, uuid, moduleName, "$entrypointMainName");
}
/* MAIN_EXTENSION_MARKER */
child.main();
})();
''';
}
/// Generate a synthetic main module which captures the application's main
/// method.
///

View file

@ -219,35 +219,69 @@ enum WebRendererMode implements CliEnum {
}
}
/// The correct precompiled artifact to use for each build and render mode.
const Map<WebRendererMode, Map<NullSafetyMode, HostArtifact>> kDartSdkJsArtifactMap = <WebRendererMode, Map<NullSafetyMode, HostArtifact>>{
/// The correct precompiled artifact to use for each build and render mode for DDC with AMD modules.
// TODO(markzipan): delete this when DDC's AMD module system is deprecated, https://github.com/flutter/flutter/issues/142060.
const Map<WebRendererMode, Map<NullSafetyMode, HostArtifact>> kAmdDartSdkJsArtifactMap = <WebRendererMode, Map<NullSafetyMode, HostArtifact>>{
WebRendererMode.auto: <NullSafetyMode, HostArtifact> {
NullSafetyMode.sound: HostArtifact.webPrecompiledCanvaskitAndHtmlSoundSdk,
NullSafetyMode.unsound: HostArtifact.webPrecompiledCanvaskitAndHtmlSdk,
NullSafetyMode.sound: HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSoundSdk,
NullSafetyMode.unsound: HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSdk,
},
WebRendererMode.canvaskit: <NullSafetyMode, HostArtifact> {
NullSafetyMode.sound: HostArtifact.webPrecompiledCanvaskitSoundSdk,
NullSafetyMode.unsound: HostArtifact.webPrecompiledCanvaskitSdk,
NullSafetyMode.sound: HostArtifact.webPrecompiledAmdCanvaskitSoundSdk,
NullSafetyMode.unsound: HostArtifact.webPrecompiledAmdCanvaskitSdk,
},
WebRendererMode.html: <NullSafetyMode, HostArtifact> {
NullSafetyMode.sound: HostArtifact.webPrecompiledSoundSdk,
NullSafetyMode.unsound: HostArtifact.webPrecompiledSdk,
NullSafetyMode.sound: HostArtifact.webPrecompiledAmdSoundSdk,
NullSafetyMode.unsound: HostArtifact.webPrecompiledAmdSdk,
},
};
/// The correct source map artifact to use for each build and render mode.
const Map<WebRendererMode, Map<NullSafetyMode, HostArtifact>> kDartSdkJsMapArtifactMap = <WebRendererMode, Map<NullSafetyMode, HostArtifact>>{
/// The correct source map artifact to use for each build and render mode for DDC with AMD modules.
// TODO(markzipan): delete this when DDC's AMD module system is deprecated, https://github.com/flutter/flutter/issues/142060.
const Map<WebRendererMode, Map<NullSafetyMode, HostArtifact>> kAmdDartSdkJsMapArtifactMap = <WebRendererMode, Map<NullSafetyMode, HostArtifact>>{
WebRendererMode.auto: <NullSafetyMode, HostArtifact> {
NullSafetyMode.sound: HostArtifact.webPrecompiledCanvaskitAndHtmlSoundSdkSourcemaps,
NullSafetyMode.unsound: HostArtifact.webPrecompiledCanvaskitAndHtmlSdkSourcemaps,
NullSafetyMode.sound: HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSoundSdkSourcemaps,
NullSafetyMode.unsound: HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSdkSourcemaps,
},
WebRendererMode.canvaskit: <NullSafetyMode, HostArtifact> {
NullSafetyMode.sound: HostArtifact.webPrecompiledCanvaskitSoundSdkSourcemaps,
NullSafetyMode.unsound: HostArtifact.webPrecompiledCanvaskitSdkSourcemaps,
NullSafetyMode.sound: HostArtifact.webPrecompiledAmdCanvaskitSoundSdkSourcemaps,
NullSafetyMode.unsound: HostArtifact.webPrecompiledAmdCanvaskitSdkSourcemaps,
},
WebRendererMode.html: <NullSafetyMode, HostArtifact> {
NullSafetyMode.sound: HostArtifact.webPrecompiledSoundSdkSourcemaps,
NullSafetyMode.unsound: HostArtifact.webPrecompiledSdkSourcemaps,
NullSafetyMode.sound: HostArtifact.webPrecompiledAmdSoundSdkSourcemaps,
NullSafetyMode.unsound: HostArtifact.webPrecompiledAmdSdkSourcemaps,
},
};
/// The correct precompiled artifact to use for each build and render mode for DDC with DDC modules.
const Map<WebRendererMode, Map<NullSafetyMode, HostArtifact>> kDdcDartSdkJsArtifactMap = <WebRendererMode, Map<NullSafetyMode, HostArtifact>>{
WebRendererMode.auto: <NullSafetyMode, HostArtifact> {
NullSafetyMode.sound: HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSoundSdk,
NullSafetyMode.unsound: HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdk,
},
WebRendererMode.canvaskit: <NullSafetyMode, HostArtifact> {
NullSafetyMode.sound: HostArtifact.webPrecompiledDdcCanvaskitSoundSdk,
NullSafetyMode.unsound: HostArtifact.webPrecompiledDdcCanvaskitSdk,
},
WebRendererMode.html: <NullSafetyMode, HostArtifact> {
NullSafetyMode.sound: HostArtifact.webPrecompiledDdcSoundSdk,
NullSafetyMode.unsound: HostArtifact.webPrecompiledDdcSdk,
},
};
/// The correct source map artifact to use for each build and render mode for DDC with DDC modules.
const Map<WebRendererMode, Map<NullSafetyMode, HostArtifact>> kDdcDartSdkJsMapArtifactMap = <WebRendererMode, Map<NullSafetyMode, HostArtifact>>{
WebRendererMode.auto: <NullSafetyMode, HostArtifact> {
NullSafetyMode.sound: HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSoundSdkSourcemaps,
NullSafetyMode.unsound: HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdkSourcemaps,
},
WebRendererMode.canvaskit: <NullSafetyMode, HostArtifact> {
NullSafetyMode.sound: HostArtifact.webPrecompiledDdcCanvaskitSoundSdkSourcemaps,
NullSafetyMode.unsound: HostArtifact.webPrecompiledDdcCanvaskitSdkSourcemaps,
},
WebRendererMode.html: <NullSafetyMode, HostArtifact> {
NullSafetyMode.sound: HostArtifact.webPrecompiledDdcSoundSdkSourcemaps,
NullSafetyMode.unsound: HostArtifact.webPrecompiledDdcSdkSourcemaps,
},
};

View file

@ -50,12 +50,18 @@ void main() {
operatingSystemUtils = FakeOperatingSystemUtils();
for (final HostArtifact artifact in <HostArtifact>[
HostArtifact.webPrecompiledCanvaskitAndHtmlSoundSdk,
HostArtifact.webPrecompiledCanvaskitAndHtmlSdk,
HostArtifact.webPrecompiledCanvaskitSoundSdk,
HostArtifact.webPrecompiledCanvaskitSdk,
HostArtifact.webPrecompiledSoundSdk,
HostArtifact.webPrecompiledSdk,
HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSoundSdk,
HostArtifact.webPrecompiledAmdCanvaskitAndHtmlSdk,
HostArtifact.webPrecompiledAmdCanvaskitSoundSdk,
HostArtifact.webPrecompiledAmdCanvaskitSdk,
HostArtifact.webPrecompiledAmdSoundSdk,
HostArtifact.webPrecompiledAmdSdk,
HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSoundSdk,
HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdk,
HostArtifact.webPrecompiledDdcCanvaskitSoundSdk,
HostArtifact.webPrecompiledDdcCanvaskitSdk,
HostArtifact.webPrecompiledDdcSoundSdk,
HostArtifact.webPrecompiledDdcSdk,
]) {
final File artifactFile = artifacts.getHostArtifact(artifact) as File;
artifactFile.createSync();
@ -63,7 +69,51 @@ void main() {
}
});
testUsingContext('FlutterWebPlatform serves the correct dart_sdk.js for the passed web renderer', () async {
testUsingContext(
'FlutterWebPlatform serves the correct dart_sdk.js (amd module system) 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.webPrecompiledAmdCanvaskitSoundSdk.name);
await webPlatform.close();
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
Logger: () => logger,
});
testUsingContext(
'FlutterWebPlatform serves the correct dart_sdk.js (ddc module system) for the passed web renderer',
() async {
final ChromiumLauncher chromiumLauncher = ChromiumLauncher(
fileSystem: fileSystem,
platform: platform,
@ -79,7 +129,8 @@ void main() {
buildInfo: const BuildInfo(
BuildMode.debug,
'',
treeShakeIcons: false
treeShakeIcons: false,
extraFrontEndOptions: <String>['--dartdevc-module-format=ddc'],
),
webMemoryFS: WebMemoryFS(),
fileSystem: fileSystem,
@ -99,7 +150,7 @@ void main() {
Uri.parse('http://localhost/dart_sdk.js'),
));
final String contents = await response.readAsString();
expect(contents, HostArtifact.webPrecompiledCanvaskitSoundSdk.name);
expect(contents, HostArtifact.webPrecompiledDdcCanvaskitSoundSdk.name);
await webPlatform.close();
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,

View file

@ -148,41 +148,76 @@ void main() {
);
});
testWithoutContext('precompiled web artifact paths are correct', () {
testWithoutContext('Precompiled web AMD module system artifact paths are correct', () {
expect(
artifacts.getHostArtifact(HostArtifact.webPrecompiledSdk).path,
artifacts.getHostArtifact(HostArtifact.webPrecompiledAmdSdk).path,
'root/bin/cache/flutter_web_sdk/kernel/amd/dart_sdk.js',
);
expect(
artifacts.getHostArtifact(HostArtifact.webPrecompiledSdkSourcemaps).path,
artifacts.getHostArtifact(HostArtifact.webPrecompiledAmdSdkSourcemaps).path,
'root/bin/cache/flutter_web_sdk/kernel/amd/dart_sdk.js.map',
);
expect(
artifacts.getHostArtifact(HostArtifact.webPrecompiledCanvaskitSdk).path,
artifacts.getHostArtifact(HostArtifact.webPrecompiledAmdCanvaskitSdk).path,
'root/bin/cache/flutter_web_sdk/kernel/amd-canvaskit/dart_sdk.js',
);
expect(
artifacts.getHostArtifact(HostArtifact.webPrecompiledCanvaskitSdkSourcemaps).path,
artifacts.getHostArtifact(HostArtifact.webPrecompiledAmdCanvaskitSdkSourcemaps).path,
'root/bin/cache/flutter_web_sdk/kernel/amd-canvaskit/dart_sdk.js.map',
);
expect(
artifacts.getHostArtifact(HostArtifact.webPrecompiledSoundSdk).path,
artifacts.getHostArtifact(HostArtifact.webPrecompiledAmdSoundSdk).path,
'root/bin/cache/flutter_web_sdk/kernel/amd-sound/dart_sdk.js',
);
expect(
artifacts.getHostArtifact(HostArtifact.webPrecompiledSoundSdkSourcemaps).path,
artifacts.getHostArtifact(HostArtifact.webPrecompiledAmdSoundSdkSourcemaps).path,
'root/bin/cache/flutter_web_sdk/kernel/amd-sound/dart_sdk.js.map',
);
expect(
artifacts.getHostArtifact(HostArtifact.webPrecompiledCanvaskitSoundSdk).path,
artifacts.getHostArtifact(HostArtifact.webPrecompiledAmdCanvaskitSoundSdk).path,
'root/bin/cache/flutter_web_sdk/kernel/amd-canvaskit-sound/dart_sdk.js',
);
expect(
artifacts.getHostArtifact(HostArtifact.webPrecompiledCanvaskitSoundSdkSourcemaps).path,
artifacts.getHostArtifact(HostArtifact.webPrecompiledAmdCanvaskitSoundSdkSourcemaps).path,
'root/bin/cache/flutter_web_sdk/kernel/amd-canvaskit-sound/dart_sdk.js.map',
);
});
testWithoutContext('Precompiled web DDC module system artifact paths are correct', () {
expect(
artifacts.getHostArtifact(HostArtifact.webPrecompiledDdcSdk).path,
'root/bin/cache/flutter_web_sdk/kernel/ddc/dart_sdk.js',
);
expect(
artifacts.getHostArtifact(HostArtifact.webPrecompiledDdcSdkSourcemaps).path,
'root/bin/cache/flutter_web_sdk/kernel/ddc/dart_sdk.js.map',
);
expect(
artifacts.getHostArtifact(HostArtifact.webPrecompiledDdcCanvaskitSdk).path,
'root/bin/cache/flutter_web_sdk/kernel/ddc-canvaskit/dart_sdk.js',
);
expect(
artifacts.getHostArtifact(HostArtifact.webPrecompiledDdcCanvaskitSdkSourcemaps).path,
'root/bin/cache/flutter_web_sdk/kernel/ddc-canvaskit/dart_sdk.js.map',
);
expect(
artifacts.getHostArtifact(HostArtifact.webPrecompiledDdcSoundSdk).path,
'root/bin/cache/flutter_web_sdk/kernel/ddc-sound/dart_sdk.js',
);
expect(
artifacts.getHostArtifact(HostArtifact.webPrecompiledDdcSoundSdkSourcemaps).path,
'root/bin/cache/flutter_web_sdk/kernel/ddc-sound/dart_sdk.js.map',
);
expect(
artifacts.getHostArtifact(HostArtifact.webPrecompiledDdcCanvaskitSoundSdk).path,
'root/bin/cache/flutter_web_sdk/kernel/ddc-canvaskit-sound/dart_sdk.js',
);
expect(
artifacts.getHostArtifact(HostArtifact.webPrecompiledDdcCanvaskitSoundSdkSourcemaps).path,
'root/bin/cache/flutter_web_sdk/kernel/ddc-canvaskit-sound/dart_sdk.js.map',
);
});
testWithoutContext('getEngineType', () {
expect(
artifacts.getEngineType(TargetPlatform.android_arm, BuildMode.debug),

View file

@ -170,4 +170,167 @@ void main() {
expect(result, contains("Uri.parse('file:///test/absolute_path.dart')"));
});
group('Using the DDC module system', () {
test('generateDDCBootstrapScript embeds urls correctly', () {
final String result = generateDDCBootstrapScript(
entrypoint: 'foo/bar/main.js',
ddcModuleLoaderUrl: 'ddc_module_loader.js',
mapperUrl: 'mapper.js',
generateLoadingIndicator: true,
);
// ddc module loader js source is interpolated correctly.
expect(result, contains('"moduleLoader": "ddc_module_loader.js"'));
expect(result, contains('"src": "ddc_module_loader.js"'));
// stack trace mapper source is interpolated correctly.
expect(result, contains('"mapper": "mapper.js"'));
expect(result, contains('"src": "mapper.js"'));
// data-main is set to correct bootstrap module.
expect(result, contains('"src": "main_module.bootstrap.js"'));
expect(result, contains('"id": "data-main"'));
});
test('generateDDCBootstrapScript initializes configuration objects', () {
final String result = generateDDCBootstrapScript(
entrypoint: 'foo/bar/main.js',
ddcModuleLoaderUrl: 'ddc_module_loader.js',
mapperUrl: 'mapper.js',
generateLoadingIndicator: true,
);
// LoadConfiguration and DDCLoader objects must be constructed.
expect(result, contains(r'new window.$dartLoader.LoadConfiguration('));
expect(result, contains(r'new window.$dartLoader.DDCLoader('));
// Specific fields must be set on the LoadConfiguration.
expect(result, contains('.bootstrapScript ='));
expect(result, contains('.loadScriptFn ='));
// DDCLoader.nextAttempt must be invoked to begin loading.
expect(result, contains('nextAttempt()'));
// Proper window objects are initialized.
expect(result, contains(r'window.$dartLoader.loadConfig ='));
expect(result, contains(r'window.$dartLoader.loader ='));
});
test('generateDDCBootstrapScript includes loading indicator', () {
final String result = generateDDCBootstrapScript(
entrypoint: 'foo/bar/main.js',
ddcModuleLoaderUrl: 'ddc_module_loader.js',
mapperUrl: 'mapper.js',
generateLoadingIndicator: true,
);
expect(result, contains('"flutter-loader"'));
expect(result, contains('"indeterminate"'));
});
test('generateDDCBootstrapScript does not include loading indicator', () {
final String result = generateDDCBootstrapScript(
entrypoint: 'foo/bar/main.js',
ddcModuleLoaderUrl: 'ddc_module_loader.js',
mapperUrl: 'mapper.js',
generateLoadingIndicator: false,
);
expect(result, isNot(contains('"flutter-loader"')));
expect(result, isNot(contains('"indeterminate"')));
});
// https://github.com/flutter/flutter/issues/107742
test('generateDDCBootstrapScript loading indicator does not trigger scrollbars', () {
final String result = generateDDCBootstrapScript(
entrypoint: 'foo/bar/main.js',
ddcModuleLoaderUrl: 'ddc_module_loader.js',
mapperUrl: 'mapper.js',
generateLoadingIndicator: true,
);
// See: https://regexr.com/6q0ft
final RegExp regex = RegExp(r'(?:\.flutter-loader\s*\{)[^}]+(?:overflow\:\s*hidden;)[^}]+}');
expect(result, matches(regex), reason: '.flutter-loader must have overflow: hidden');
});
test('generateDDCMainModule embeds the entrypoint correctly', () {
final String result = generateDDCMainModule(
entrypoint: 'main.js',
nullAssertions: false,
nativeNullAssertions: false,
);
// bootstrap main module has correct defined module.
expect(result, contains('let appName = "main.js"'));
expect(result, contains('let moduleName = "main.js"'));
expect(result, contains('dart_library.start(appName, uuid, moduleName, "main");'));
});
test('generateDDCMainModule embeds its exported main correctly', () {
final String result = generateDDCMainModule(
entrypoint: 'foo/bar/main.js',
nullAssertions: false,
nativeNullAssertions: false,
exportedMain: 'foo__bar__main'
);
// bootstrap main module has correct defined module.
expect(result, contains('let appName = "foo/bar/main.js"'));
expect(result, contains('let moduleName = "foo/bar/main.js"'));
expect(result, contains('dart_library.start(appName, uuid, moduleName, "foo__bar__main");'));
});
test('generateDDCMainModule includes null safety switches', () {
final String result = generateDDCMainModule(
entrypoint: 'main.js',
nullAssertions: true,
nativeNullAssertions: true,
);
expect(result, contains('''dart.nonNullAsserts(true);'''));
expect(result, contains('''dart.nativeNonNullAsserts(true);'''));
});
test('generateDDCMainModule can disable null safety switches', () {
final String result = generateDDCMainModule(
entrypoint: 'main.js',
nullAssertions: false,
nativeNullAssertions: false,
);
expect(result, contains('''dart.nonNullAsserts(false);'''));
expect(result, contains('''dart.nativeNonNullAsserts(false);'''));
});
test('generateTestBootstrapFileContents embeds urls correctly', () {
final String result = generateTestBootstrapFileContents('foo.dart.js', 'require.js', 'mapper.js');
expect(result, contains('el.setAttribute("data-main", \'foo.dart.js\');'));
});
test('generateTestEntrypoint does not generate test config wrappers when testConfigPath is not passed', () {
final String result = generateTestEntrypoint(
relativeTestPath: 'relative_path.dart',
absolutePath: 'absolute_path.dart',
testConfigPath: null,
languageVersion: LanguageVersion(2, 8),
);
expect(result, isNot(contains('test_config.testExecutable')));
});
test('generateTestEntrypoint generates test config wrappers when testConfigPath is passed', () {
final String result = generateTestEntrypoint(
relativeTestPath: 'relative_path.dart',
absolutePath: 'absolute_path.dart',
testConfigPath: 'test_config_path.dart',
languageVersion: LanguageVersion(2, 8),
);
expect(result, contains('test_config.testExecutable'));
});
test('generateTestEntrypoint embeds urls correctly', () {
final String result = generateTestEntrypoint(
relativeTestPath: 'relative_path.dart',
absolutePath: '/test/absolute_path.dart',
testConfigPath: null,
languageVersion: LanguageVersion(2, 8),
);
expect(result, contains("Uri.parse('file:///test/absolute_path.dart')"));
});
});
}

File diff suppressed because it is too large Load diff

View file

@ -46,6 +46,7 @@ void main() {
late Platform windows;
late FakeHttpServer httpServer;
late BufferLogger logger;
const bool usesDdcModuleSystem = false;
setUpAll(() async {
packages = PackageConfig(<Package>[
@ -66,6 +67,7 @@ void main() {
<String, String>{},
<String, String>{},
NullSafetyMode.unsound,
usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit,
);
releaseAssetServer = ReleaseAssetServer(
@ -292,6 +294,7 @@ void main() {
<String, String>{},
<String, String>{},
NullSafetyMode.unsound,
usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit,
);
@ -312,6 +315,7 @@ void main() {
<String, String>{},
<String, String>{},
NullSafetyMode.unsound,
usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit,
);
@ -334,6 +338,7 @@ void main() {
<String, String>{},
<String, String>{},
NullSafetyMode.unsound,
usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit,
),
throwsToolExit(),
@ -355,6 +360,7 @@ void main() {
<String, String>{},
<String, String>{},
NullSafetyMode.unsound,
usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit,
),
throwsToolExit(),
@ -652,7 +658,7 @@ void main() {
expect(httpServer.closed, true);
}));
test('Can start web server with specified assets', () => testbed.run(() async {
test('Can start web server with specified AMD module system assets', () => testbed.run(() async {
final File outputFile = globals.fs.file(globals.fs.path.join('lib', 'main.dart'))
..createSync(recursive: true);
outputFile.parent.childFile('a.sources').writeAsStringSync('');
@ -689,6 +695,7 @@ void main() {
extraHeaders: const <String, String>{},
chromiumLauncher: null,
nullSafetyMode: NullSafetyMode.unsound,
ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.html,
);
webDevFS.requireJS.createSync(recursive: true);
@ -698,13 +705,13 @@ void main() {
final Uri uri = await webDevFS.create();
webDevFS.webAssetServer.entrypointCacheDirectory = globals.fs.currentDirectory;
final String webPrecompiledSdk = globals.artifacts!
.getHostArtifact(HostArtifact.webPrecompiledSdk).path;
.getHostArtifact(HostArtifact.webPrecompiledAmdSdk).path;
final String webPrecompiledSdkSourcemaps = globals.artifacts!
.getHostArtifact(HostArtifact.webPrecompiledSdkSourcemaps).path;
.getHostArtifact(HostArtifact.webPrecompiledAmdSdkSourcemaps).path;
final String webPrecompiledCanvaskitSdk = globals.artifacts!
.getHostArtifact(HostArtifact.webPrecompiledCanvaskitSdk).path;
.getHostArtifact(HostArtifact.webPrecompiledAmdCanvaskitSdk).path;
final String webPrecompiledCanvaskitSdkSourcemaps = globals.artifacts!
.getHostArtifact(HostArtifact.webPrecompiledCanvaskitSdkSourcemaps).path;
.getHostArtifact(HostArtifact.webPrecompiledAmdCanvaskitSdkSourcemaps).path;
globals.fs.currentDirectory
.childDirectory('lib')
.childFile('web_entrypoint.dart')
@ -799,6 +806,7 @@ void main() {
extraHeaders: const <String, String>{},
chromiumLauncher: null,
nullSafetyMode: NullSafetyMode.sound,
ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.html,
);
webDevFS.requireJS.createSync(recursive: true);
@ -813,13 +821,13 @@ void main() {
..createSync(recursive: true)
..writeAsStringSync('GENERATED');
final String webPrecompiledSdk = globals.artifacts!
.getHostArtifact(HostArtifact.webPrecompiledSoundSdk).path;
.getHostArtifact(HostArtifact.webPrecompiledAmdSoundSdk).path;
final String webPrecompiledSdkSourcemaps = globals.artifacts!
.getHostArtifact(HostArtifact.webPrecompiledSoundSdkSourcemaps).path;
.getHostArtifact(HostArtifact.webPrecompiledAmdSoundSdkSourcemaps).path;
final String webPrecompiledCanvaskitSdk = globals.artifacts!
.getHostArtifact(HostArtifact.webPrecompiledCanvaskitSoundSdk).path;
.getHostArtifact(HostArtifact.webPrecompiledAmdCanvaskitSoundSdk).path;
final String webPrecompiledCanvaskitSdkSourcemaps = globals.artifacts!
.getHostArtifact(HostArtifact.webPrecompiledCanvaskitSoundSdkSourcemaps).path;
.getHostArtifact(HostArtifact.webPrecompiledAmdCanvaskitSoundSdkSourcemaps).path;
globals.fs.file(webPrecompiledSdk)
..createSync(recursive: true)
..writeAsStringSync('HELLO');
@ -908,6 +916,7 @@ void main() {
extraHeaders: const <String, String>{},
chromiumLauncher: null,
nullSafetyMode: NullSafetyMode.sound,
ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit,
);
webDevFS.requireJS.createSync(recursive: true);
@ -970,6 +979,7 @@ void main() {
nullAssertions: true,
nativeNullAssertions: true,
nullSafetyMode: NullSafetyMode.sound,
ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit,
);
webDevFS.requireJS.createSync(recursive: true);
@ -1016,6 +1026,7 @@ void main() {
extraHeaders: const <String, String>{},
chromiumLauncher: null,
nullSafetyMode: NullSafetyMode.sound,
ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit,
);
webDevFS.requireJS.createSync(recursive: true);
@ -1063,6 +1074,7 @@ void main() {
extraHeaders: const <String, String>{},
chromiumLauncher: null,
nullSafetyMode: NullSafetyMode.sound,
ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.auto,
);
webDevFS.requireJS.createSync(recursive: true);
@ -1111,6 +1123,7 @@ void main() {
extraHeaders: const <String, String>{},
chromiumLauncher: null,
nullSafetyMode: NullSafetyMode.unsound,
ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit,
);
webDevFS.requireJS.createSync(recursive: true);
@ -1219,6 +1232,7 @@ void main() {
<String, String>{},
<String, String>{},
NullSafetyMode.sound,
usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit,
);
@ -1262,6 +1276,7 @@ void main() {
extraHeaders: const <String, String>{},
chromiumLauncher: null,
nullSafetyMode: NullSafetyMode.unsound,
ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.canvaskit,
);
webDevFS.requireJS.createSync(recursive: true);