Support DDC library bundle format and remove support for DDC module format (#161276)

This gets us closer to enabling [hot
reload](https://github.com/dart-lang/sdk/issues/54934) on the web as
this format is a prerequisite. Historically, we added support for the
DDC module format only to enable hot reload, but that format is not
feasible for the goal, so we added the DDC library bundle format. The
DDC library bundle format is currently represented as the combination of
the `ddc` module format and `canary`. We no longer need to support the
old DDC module format.

- Adds build artifacts to build the SDKs for this format (but only in
sound mode as unsound is unsupported), and removes said artifacts for
the DDC module format.
- Update artifact maps and constants to add the new format and remove
the old format.
- Adds handling of the `canaryFeatures` flag.
- Update dwds to 24.3.0 and use the new
`FrontendServerDdcLibraryBundleStrategyProvider`.
- Add bootstrap code for the new format. Kept DDC module format
bootstrap code as it's used internally.
- Updates tests.

I ran `spinning_square` with the new module format to verify that it can
run.

## Pre-launch Checklist

- [X] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [X] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [X] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [X] I signed the [CLA].
- [X] I listed at least one issue that this PR fixes in the description
above.
- [X] I updated/added relevant documentation (doc comments with `///`).
- [X] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [ ] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [X] All existing and new tests are passing.
This commit is contained in:
Srujan Gaddam 2025-01-09 12:36:43 -08:00 committed by GitHub
parent fe73879f95
commit a38abc864c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 449 additions and 438 deletions

View File

@ -336,13 +336,17 @@ group("flutter_platform_dills") {
]
}
template("_compile_ddc_modules") {
template("_compile_ddc_module") {
assert(defined(invoker.sound_null_safety),
"sound_null_safety must be defined for $target_name")
assert(defined(invoker.use_skia),
"use_skia must be defined for $target_name")
assert(defined(invoker.use_skia), "use_skia must be defined for $target_name")
assert(defined(invoker.auto_detect),
"auto_detect must be defined for $target_name")
assert(defined(invoker.sdk_path_prefix),
"sdk_path_prefix must be defined for $target_name")
assert(defined(invoker.module_format),
"module_name must be defined for $target_name")
assert(defined(invoker.canary), "canary must be defined for $target_name")
_dartdevc(target_name) {
inputs = [ "sdk_rewriter.dart" ] + web_ui_sources
@ -360,17 +364,11 @@ template("_compile_ddc_modules") {
name_suffix += "-sound"
}
amd_js_path =
"$root_out_dir/flutter_web_sdk/kernel/amd${name_suffix}/dart_sdk.js"
ddc_js_path =
"$root_out_dir/flutter_web_sdk/kernel/ddc${name_suffix}/dart_sdk.js"
dart_sdk_js_path = "$root_out_dir/flutter_web_sdk/kernel/${invoker.sdk_path_prefix}${name_suffix}/dart_sdk.js"
outputs = [
amd_js_path,
amd_js_path + ".map",
ddc_js_path,
ddc_js_path + ".map",
dart_sdk_js_path,
dart_sdk_js_path + ".map",
]
if (invoker.sound_null_safety) {
@ -405,14 +403,13 @@ template("_compile_ddc_modules") {
"-DFLUTTER_WEB_USE_SKIA=${invoker.use_skia}",
"-DFLUTTER_WEB_AUTO_DETECT=${invoker.auto_detect}",
"--modules",
"amd",
invoker.module_format,
"-o",
rebase_path(amd_js_path),
"--modules",
"ddc",
"-o",
rebase_path(ddc_js_path),
rebase_path(dart_sdk_js_path),
]
if (invoker.canary) {
args += [ "--canary" ]
}
if (flutter_prebuilt_dart_sdk) {
args += [
"--multi-root",
@ -427,6 +424,30 @@ template("_compile_ddc_modules") {
}
}
template("_compile_ddc_modules") {
assert(defined(invoker.sound_null_safety),
"sound_null_safety must be defined for $target_name")
forward_variables_from(invoker, "*")
# We compile multiple times instead of passing multiple modules to a single
# compile as the DDC library bundle format cannot be used when passing
# multiple module formats as arguments.
_compile_ddc_module("${target_name}_amd") {
sdk_path_prefix = "amd"
module_format = "amd"
canary = false
}
# No support for unsound null safety with the DDC library bundle format.
if (sound_null_safety) {
_compile_ddc_module("${target_name}_ddcLibraryBundle") {
sdk_path_prefix = "ddcLibraryBundle"
module_format = "ddc"
canary = true
}
}
}
# Compiles the unsound html only renderer.
_compile_ddc_modules("flutter_dartdevc_kernel_sdk") {
sound_null_safety = false
@ -471,12 +492,15 @@ _compile_ddc_modules("flutter_dartdevc_canvaskit_html_kernel_sdk_sound") {
group("flutter_ddc_modules") {
public_deps = [
":flutter_dartdevc_canvaskit_html_kernel_sdk",
":flutter_dartdevc_canvaskit_html_kernel_sdk_sound",
":flutter_dartdevc_canvaskit_kernel_sdk",
":flutter_dartdevc_canvaskit_kernel_sdk_sound",
":flutter_dartdevc_kernel_sdk",
":flutter_dartdevc_kernel_sdk_sound",
":flutter_dartdevc_canvaskit_html_kernel_sdk_amd",
":flutter_dartdevc_canvaskit_html_kernel_sdk_sound_amd",
":flutter_dartdevc_canvaskit_html_kernel_sdk_sound_ddcLibraryBundle",
":flutter_dartdevc_canvaskit_kernel_sdk_amd",
":flutter_dartdevc_canvaskit_kernel_sdk_sound_amd",
":flutter_dartdevc_canvaskit_kernel_sdk_sound_ddcLibraryBundle",
":flutter_dartdevc_kernel_sdk_amd",
":flutter_dartdevc_kernel_sdk_sound_amd",
":flutter_dartdevc_kernel_sdk_sound_ddcLibraryBundle",
]
}
@ -500,14 +524,21 @@ if (!is_fuchsia) {
deps += [ "//flutter/lib/web_ui/flutter_js" ]
# flutter_ddc_modules
sources = get_target_outputs(":flutter_dartdevc_kernel_sdk")
sources += get_target_outputs(":flutter_dartdevc_canvaskit_kernel_sdk")
sources += get_target_outputs(":flutter_dartdevc_canvaskit_html_kernel_sdk")
sources += get_target_outputs(":flutter_dartdevc_kernel_sdk_sound")
sources = get_target_outputs(":flutter_dartdevc_kernel_sdk_amd")
sources += get_target_outputs(":flutter_dartdevc_canvaskit_kernel_sdk_amd")
sources +=
get_target_outputs(":flutter_dartdevc_canvaskit_kernel_sdk_sound")
get_target_outputs(":flutter_dartdevc_canvaskit_html_kernel_sdk_amd")
sources += get_target_outputs(":flutter_dartdevc_kernel_sdk_sound_amd")
sources +=
get_target_outputs(":flutter_dartdevc_canvaskit_html_kernel_sdk_sound")
get_target_outputs(":flutter_dartdevc_canvaskit_kernel_sdk_sound_amd")
sources += get_target_outputs(
":flutter_dartdevc_canvaskit_html_kernel_sdk_sound_amd")
sources += get_target_outputs(
":flutter_dartdevc_kernel_sdk_sound_ddcLibraryBundle")
sources += get_target_outputs(
":flutter_dartdevc_canvaskit_kernel_sdk_sound_ddcLibraryBundle")
sources += get_target_outputs(
":flutter_dartdevc_canvaskit_html_kernel_sdk_sound_ddcLibraryBundle")
# flutter_platform_dills
sources +=

View File

@ -119,19 +119,15 @@ enum HostArtifact {
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,
/// The precompiled SDKs and sourcemaps for web debug builds with the DDC
/// library bundle module system. Only SDKs built with sound null-safety are
/// provided here.
webPrecompiledDdcLibraryBundleSoundSdk,
webPrecompiledDdcLibraryBundleSoundSdkSourcemaps,
webPrecompiledDdcLibraryBundleCanvaskitSoundSdk,
webPrecompiledDdcLibraryBundleCanvaskitSoundSdkSourcemaps,
webPrecompiledDdcLibraryBundleCanvaskitAndHtmlSoundSdk,
webPrecompiledDdcLibraryBundleCanvaskitAndHtmlSoundSdkSourcemaps,
iosDeploy,
idevicesyslog,
@ -289,12 +285,9 @@ String _hostArtifactToFileName(HostArtifact artifact, Platform platform) {
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:
case HostArtifact.webPrecompiledDdcLibraryBundleSoundSdk:
case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSoundSdk:
case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitAndHtmlSoundSdk:
return 'dart_sdk.js';
case HostArtifact.webPrecompiledAmdSdkSourcemaps:
case HostArtifact.webPrecompiledAmdCanvaskitSdkSourcemaps:
@ -302,12 +295,9 @@ String _hostArtifactToFileName(HostArtifact artifact, Platform platform) {
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:
case HostArtifact.webPrecompiledDdcLibraryBundleSoundSdkSourcemaps:
case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSoundSdkSourcemaps:
case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitAndHtmlSoundSdkSourcemaps:
return 'dart_sdk.js.map';
case HostArtifact.impellerc:
return 'impellerc$exe';
@ -547,57 +537,30 @@ class CachedArtifacts implements Artifacts {
_hostArtifactToFileName(artifact, _platform),
);
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcSdk:
case HostArtifact.webPrecompiledDdcSdkSourcemaps:
case HostArtifact.webPrecompiledDdcLibraryBundleSoundSdk:
case HostArtifact.webPrecompiledDdcLibraryBundleSoundSdkSourcemaps:
final String path = _fileSystem.path.join(
_getFlutterWebSdkPath(),
'kernel',
'ddc',
'ddcLibraryBundle-sound',
_hostArtifactToFileName(artifact, _platform),
);
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcCanvaskitSdk:
case HostArtifact.webPrecompiledDdcCanvaskitSdkSourcemaps:
case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSoundSdk:
case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSoundSdkSourcemaps:
final String path = _fileSystem.path.join(
_getFlutterWebSdkPath(),
'kernel',
'ddc-canvaskit',
'ddcLibraryBundle-canvaskit-sound',
_hostArtifactToFileName(artifact, _platform),
);
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdk:
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdkSourcemaps:
case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitAndHtmlSoundSdk:
case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitAndHtmlSoundSdkSourcemaps:
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',
'ddcLibraryBundle-canvaskit-html-sound',
_hostArtifactToFileName(artifact, _platform),
);
return _fileSystem.file(path);
@ -1313,57 +1276,30 @@ class CachedLocalEngineArtifacts implements Artifacts {
_hostArtifactToFileName(artifact, _platform),
);
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcSdk:
case HostArtifact.webPrecompiledDdcSdkSourcemaps:
case HostArtifact.webPrecompiledDdcLibraryBundleSoundSdk:
case HostArtifact.webPrecompiledDdcLibraryBundleSoundSdkSourcemaps:
final String path = _fileSystem.path.join(
_getFlutterWebSdkPath(),
'kernel',
'ddc',
'ddcLibraryBundle-sound',
_hostArtifactToFileName(artifact, _platform),
);
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcCanvaskitSdk:
case HostArtifact.webPrecompiledDdcCanvaskitSdkSourcemaps:
case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSoundSdk:
case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSoundSdkSourcemaps:
final String path = _fileSystem.path.join(
_getFlutterWebSdkPath(),
'kernel',
'ddc-canvaskit',
'ddcLibraryBundle-canvaskit-sound',
_hostArtifactToFileName(artifact, _platform),
);
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdk:
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdkSourcemaps:
case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitAndHtmlSoundSdk:
case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitAndHtmlSoundSdkSourcemaps:
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',
'ddcLibraryBundle-canvaskit-html-sound',
_hostArtifactToFileName(artifact, _platform),
);
return _fileSystem.file(path);
@ -1791,57 +1727,30 @@ class CachedLocalWebSdkArtifacts implements Artifacts {
_hostArtifactToFileName(artifact, _platform),
);
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcSdk:
case HostArtifact.webPrecompiledDdcSdkSourcemaps:
case HostArtifact.webPrecompiledDdcLibraryBundleSoundSdk:
case HostArtifact.webPrecompiledDdcLibraryBundleSoundSdkSourcemaps:
final String path = _fileSystem.path.join(
_getFlutterWebSdkPath(),
'kernel',
'ddc',
'ddcLibraryBundle-sound',
_hostArtifactToFileName(artifact, _platform),
);
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcCanvaskitSdk:
case HostArtifact.webPrecompiledDdcCanvaskitSdkSourcemaps:
case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSoundSdk:
case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSoundSdkSourcemaps:
final String path = _fileSystem.path.join(
_getFlutterWebSdkPath(),
'kernel',
'ddc-canvaskit',
'ddcLibraryBundle-canvaskit-sound',
_hostArtifactToFileName(artifact, _platform),
);
return _fileSystem.file(path);
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdk:
case HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdkSourcemaps:
case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitAndHtmlSoundSdk:
case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitAndHtmlSoundSdkSourcemaps:
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',
'ddcLibraryBundle-canvaskit-html-sound',
_hostArtifactToFileName(artifact, _platform),
);
return _fileSystem.file(path);

View File

@ -265,9 +265,16 @@ 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.
/// The module system DDC is targeting, or null if not using DDC or the
/// associated flag isn't present.
// TODO(markzipan): delete this when DDC's AMD module system is deprecated, https://github.com/flutter/flutter/issues/142060.
DdcModuleFormat? get ddcModuleFormat => _ddcModuleFormatFromFrontEndArgs(extraFrontEndOptions);
DdcModuleFormat? get ddcModuleFormat =>
_ddcModuleFormatAndCanaryFeaturesFromFrontEndArgs(extraFrontEndOptions).ddcModuleFormat;
/// Whether to enable canary features when using DDC, or null if not using
/// DDC or the associated flag isn't present.
bool? get canaryFeatures =>
_ddcModuleFormatAndCanaryFeaturesFromFrontEndArgs(extraFrontEndOptions).canaryFeatures;
/// Convert to a structured string encoded structure appropriate for usage
/// in build system [Environment.defines].
@ -1041,18 +1048,24 @@ enum NullSafetyMode {
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=';
({DdcModuleFormat? ddcModuleFormat, bool? canaryFeatures})
_ddcModuleFormatAndCanaryFeaturesFromFrontEndArgs(List<String>? extraFrontEndArgs) {
DdcModuleFormat? ddcModuleFormat;
bool? canaryFeatures;
if (extraFrontEndArgs != null) {
const String ddcModuleFormatArg = '--dartdevc-module-format=';
const String canaryFeaturesArg = '--dartdevc-canary';
for (final String flag in extraFrontEndArgs) {
if (flag.startsWith(ddcModuleFormatString)) {
final String moduleFormatString = flag.substring(ddcModuleFormatString.length, flag.length);
return DdcModuleFormat.values.byName(moduleFormatString);
if (flag.startsWith(ddcModuleFormatArg)) {
final String moduleFormatString = flag.substring(ddcModuleFormatArg.length, flag.length);
assert(ddcModuleFormat == null);
ddcModuleFormat = DdcModuleFormat.values.byName(moduleFormatString);
} else if (flag == canaryFeaturesArg) {
canaryFeatures = true;
}
}
return null;
}
return (ddcModuleFormat: ddcModuleFormat, canaryFeatures: canaryFeatures);
}
String _getCurrentHostPlatformArchName() {

View File

@ -125,10 +125,17 @@ class WebAssetServer implements AssetReader {
this._modules,
this._digests,
this._nullSafetyMode,
this._ddcModuleSystem, {
this._ddcModuleSystem,
this._canaryFeatures, {
required this.webRenderer,
required this.useLocalCanvasKit,
}) : basePath = _getWebTemplate('index.html', _kDefaultIndex).getBaseHref();
}) : basePath = _getWebTemplate('index.html', _kDefaultIndex).getBaseHref() {
// TODO(srujzs): Remove this assertion when the library bundle format is
// supported without canary mode.
if (_ddcModuleSystem) {
assert(_canaryFeatures);
}
}
// Fallback to "application/octet-stream" on null which
// makes no claims as to the structure of the data.
@ -188,7 +195,13 @@ class WebAssetServer implements AssetReader {
DwdsLauncher dwdsLauncher = Dwds.start,
// TODO(markzipan): Make sure this default value aligns with that in the debugger options.
bool ddcModuleSystem = false,
bool canaryFeatures = false,
}) async {
// TODO(srujzs): Remove this assertion when the library bundle format is
// supported without canary mode.
if (ddcModuleSystem) {
assert(canaryFeatures);
}
InternetAddress address;
if (hostname == 'any') {
address = InternetAddress.anyIPv4;
@ -236,6 +249,7 @@ class WebAssetServer implements AssetReader {
digests,
nullSafetyMode,
ddcModuleSystem,
canaryFeatures,
webRenderer: webRenderer,
useLocalCanvasKit: useLocalCanvasKit,
);
@ -300,7 +314,7 @@ class WebAssetServer implements AssetReader {
toolConfiguration: ToolConfiguration(
loadStrategy:
ddcModuleSystem
? FrontendServerDdcStrategyProvider(
? FrontendServerDdcLibraryBundleStrategyProvider(
ReloadConfiguration.none,
server,
PackageUriMapper(packageConfig),
@ -356,6 +370,7 @@ class WebAssetServer implements AssetReader {
final NullSafetyMode _nullSafetyMode;
final bool _ddcModuleSystem;
final bool _canaryFeatures;
final HttpServer _httpServer;
final WebMemoryFS _webMemoryFS = WebMemoryFS();
final PackageConfig _packages;
@ -674,7 +689,7 @@ _flutter.buildConfig = ${jsonEncode(buildConfig)};
File get _resolveDartSdkJsFile {
final Map<WebRendererMode, Map<NullSafetyMode, HostArtifact>> dartSdkArtifactMap =
_ddcModuleSystem ? kDdcDartSdkJsArtifactMap : kAmdDartSdkJsArtifactMap;
_ddcModuleSystem ? kDdcLibraryBundleDartSdkJsArtifactMap : kAmdDartSdkJsArtifactMap;
return globals.fs.file(
globals.artifacts!.getHostArtifact(dartSdkArtifactMap[webRenderer]![_nullSafetyMode]!),
);
@ -682,7 +697,7 @@ _flutter.buildConfig = ${jsonEncode(buildConfig)};
File get _resolveDartSdkJsMapFile {
final Map<WebRendererMode, Map<NullSafetyMode, HostArtifact>> dartSdkArtifactMap =
_ddcModuleSystem ? kDdcDartSdkJsMapArtifactMap : kAmdDartSdkJsMapArtifactMap;
_ddcModuleSystem ? kDdcLibraryBundleDartSdkJsMapArtifactMap : kAmdDartSdkJsMapArtifactMap;
return globals.fs.file(
globals.artifacts!.getHostArtifact(dartSdkArtifactMap[webRenderer]![_nullSafetyMode]!),
);
@ -762,12 +777,19 @@ class WebDevFS implements DevFS {
required this.nativeNullAssertions,
required this.nullSafetyMode,
required this.ddcModuleSystem,
required this.canaryFeatures,
required this.webRenderer,
required this.isWasm,
required this.useLocalCanvasKit,
required this.rootDirectory,
this.testMode = false,
}) : _port = port;
}) : _port = port {
// TODO(srujzs): Remove this assertion when the library bundle format is
// supported without canary mode.
if (ddcModuleSystem) {
assert(canaryFeatures);
}
}
final Uri entrypoint;
final String hostname;
@ -782,6 +804,7 @@ class WebDevFS implements DevFS {
final Map<String, String> extraHeaders;
final bool testMode;
final bool ddcModuleSystem;
final bool canaryFeatures;
final ExpressionCompiler? expressionCompiler;
final ChromiumLauncher? chromiumLauncher;
final bool nullAssertions;
@ -894,6 +917,7 @@ class WebDevFS implements DevFS {
useLocalCanvasKit: useLocalCanvasKit,
testMode: testMode,
ddcModuleSystem: ddcModuleSystem,
canaryFeatures: canaryFeatures,
);
final int selectedPort = webAssetServer.selectedPort;
@ -983,7 +1007,7 @@ class WebDevFS implements DevFS {
webAssetServer.writeFile(
'main.dart.js',
ddcModuleSystem
? generateDDCBootstrapScript(
? generateDDCLibraryBundleBootstrapScript(
entrypoint: entrypoint,
ddcModuleLoaderUrl: 'ddc_module_loader.js',
mapperUrl: 'stack_trace_mapper.js',
@ -998,11 +1022,10 @@ class WebDevFS implements DevFS {
webAssetServer.writeFile(
'main_module.bootstrap.js',
ddcModuleSystem
? generateDDCMainModule(
? generateDDCLibraryBundleMainModule(
entrypoint: entrypoint,
nullAssertions: nullAssertions,
nativeNullAssertions: nativeNullAssertions,
exportedMain: pathToJSIdentifier(entrypoint.split('.')[0]),
)
: generateMainModule(
entrypoint: entrypoint,

View File

@ -314,6 +314,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
nullSafetyMode: debuggingOptions.buildInfo.nullSafetyMode,
nativeNullAssertions: debuggingOptions.nativeNullAssertions,
ddcModuleSystem: debuggingOptions.buildInfo.ddcModuleFormat == DdcModuleFormat.ddc,
canaryFeatures: debuggingOptions.buildInfo.canaryFeatures ?? false,
webRenderer: debuggingOptions.webRenderer,
isWasm: debuggingOptions.webUseWasm,
useLocalCanvasKit: debuggingOptions.buildInfo.useLocalCanvasKit,

View File

@ -293,9 +293,14 @@ class FlutterWebPlatform extends PlatformPlugin {
);
File get _dartSdk {
// TODO(srujzs): Remove this assertion when the library bundle format is
// supported without canary mode.
if (buildInfo.ddcModuleFormat == DdcModuleFormat.ddc) {
assert(buildInfo.canaryFeatures ?? true);
}
final Map<WebRendererMode, Map<NullSafetyMode, HostArtifact>> dartSdkArtifactMap =
buildInfo.ddcModuleFormat == DdcModuleFormat.ddc
? kDdcDartSdkJsArtifactMap
? kDdcLibraryBundleDartSdkJsArtifactMap
: kAmdDartSdkJsArtifactMap;
return _fileSystem.file(
_artifacts!.getHostArtifact(dartSdkArtifactMap[webRenderer]![_nullSafetyMode]!),
@ -303,9 +308,14 @@ class FlutterWebPlatform extends PlatformPlugin {
}
File get _dartSdkSourcemaps {
// TODO(srujzs): Remove this assertion when the library bundle format is
// supported without canary mode.
if (buildInfo.ddcModuleFormat == DdcModuleFormat.ddc) {
assert(buildInfo.canaryFeatures ?? true);
}
final Map<WebRendererMode, Map<NullSafetyMode, HostArtifact>> dartSdkArtifactMap =
buildInfo.ddcModuleFormat == DdcModuleFormat.ddc
? kDdcDartSdkJsMapArtifactMap
? kDdcLibraryBundleDartSdkJsMapArtifactMap
: kAmdDartSdkJsMapArtifactMap;
return _fileSystem.file(
_artifacts!.getHostArtifact(dartSdkArtifactMap[webRenderer]![_nullSafetyMode]!),

View File

@ -4,20 +4,17 @@
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";
/// Used to load prerequisite scripts such as ddc_module_loader.js
const String _simpleLoaderScript = r'''
// Declare the character set of the document to align with require.js. Using a
// meta element is preferable to changing the individual script elements'
// `charset` as the scripts should inherit the document's character set, and
// modifying a script element's character set is deprecated.
var meta = document.createElement('meta');
meta.charset = 'utf-8';
document.head.insertBefore(meta, document.head.firstChild);
window.\$dartCreateScript = (function() {
window.$dartCreateScript = (function() {
// Find the nonce value. (Note, this is only computed once.)
var scripts = Array.from(document.getElementsByTagName("script"));
var nonce;
@ -43,7 +40,7 @@ window.\$dartCreateScript = (function() {
var forceLoadModule = function (relativeUrl, root) {
var actualRoot = root ?? _currentDirectory;
return new Promise(function(resolve, reject) {
var script = self.\$dartCreateScript();
var script = self.$dartCreateScript();
let policy = {
createScriptURL: function(src) {return src;}
};
@ -56,6 +53,23 @@ var forceLoadModule = function (relativeUrl, root) {
document.head.appendChild(script);
});
};
''';
// TODO(srujzs): Delete this once it's no longer used internally.
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";
$_simpleLoaderScript
// A map containing the URLs for the bootstrap scripts in debug.
let _scriptUrls = {
@ -134,6 +148,91 @@ let _scriptUrls = {
''';
}
String generateDDCLibraryBundleBootstrapScript({
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";
$_simpleLoaderScript
// A map containing the URLs for the bootstrap scripts in debug.
let _scriptUrls = {
"mapper": "$mapperUrl",
"moduleLoader": "$ddcModuleLoaderUrl"
};
(function() {
// 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());
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;
// TODO(srujzs): Support hot restart.
// Begin loading libraries
loader.nextAttempt();
}
})();
''';
}
/// The JavaScript bootstrap script to support in-browser hot restart.
///
/// The [requireUrl] loads our cached RequireJS script file. The [mapperUrl]
@ -287,6 +386,7 @@ document.addEventListener('dart-app-ready', function (e) {
''';
}
// TODO(srujzs): Delete this once it's no longer used internally.
String generateDDCMainModule({
required String entrypoint,
required bool nullAssertions,
@ -320,6 +420,35 @@ String generateDDCMainModule({
''';
}
String generateDDCLibraryBundleMainModule({
required String entrypoint,
required bool nullAssertions,
required bool nativeNullAssertions,
}) {
// The typo below in "EXTENTION" is load-bearing, package:build depends on it.
return '''
/* ENTRYPOINT_EXTENTION_MARKER */
(function() {
let appName = "org-dartlang-app:/$entrypoint";
dartDevEmbedder.debugger.registerDevtoolsFormatter();
let child = {};
child.main = function() {
let sdkOptions = {
nonNullAsserts: $nullAssertions,
nativeNonNullAsserts: $nativeNullAssertions,
};
dartDevEmbedder.runMain(appName, sdkOptions);
}
/* MAIN_EXTENSION_MARKER */
child.main();
})();
''';
}
/// Generate a synthetic main module which captures the application's main
/// method.
///

View File

@ -296,37 +296,36 @@ const Map<WebRendererMode, Map<NullSafetyMode, HostArtifact>> kAmdDartSdkJsMapAr
},
};
/// 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>>{
/// The correct precompiled artifact to use for each build and render mode for
/// DDC with DDC library bundle module format. Only artifacts with sound
/// null-safety are provided.
const Map<WebRendererMode, Map<NullSafetyMode, HostArtifact>>
kDdcLibraryBundleDartSdkJsArtifactMap = <WebRendererMode, Map<NullSafetyMode, HostArtifact>>{
WebRendererMode.auto: <NullSafetyMode, HostArtifact>{
NullSafetyMode.sound: HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSoundSdk,
NullSafetyMode.unsound: HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdk,
NullSafetyMode.sound: HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitAndHtmlSoundSdk,
},
WebRendererMode.canvaskit: <NullSafetyMode, HostArtifact>{
NullSafetyMode.sound: HostArtifact.webPrecompiledDdcCanvaskitSoundSdk,
NullSafetyMode.unsound: HostArtifact.webPrecompiledDdcCanvaskitSdk,
NullSafetyMode.sound: HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSoundSdk,
},
WebRendererMode.html: <NullSafetyMode, HostArtifact>{
NullSafetyMode.sound: HostArtifact.webPrecompiledDdcSoundSdk,
NullSafetyMode.unsound: HostArtifact.webPrecompiledDdcSdk,
NullSafetyMode.sound: HostArtifact.webPrecompiledDdcLibraryBundleSoundSdk,
},
};
/// 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>>{
/// The correct source map artifact to use for each build and render mode for
/// DDC with DDC library bundle module format. Only artifacts with sound
/// null-safety are provided.
const Map<WebRendererMode, Map<NullSafetyMode, HostArtifact>>
kDdcLibraryBundleDartSdkJsMapArtifactMap = <WebRendererMode, Map<NullSafetyMode, HostArtifact>>{
WebRendererMode.auto: <NullSafetyMode, HostArtifact>{
NullSafetyMode.sound: HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSoundSdkSourcemaps,
NullSafetyMode.unsound: HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdkSourcemaps,
NullSafetyMode.sound:
HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitAndHtmlSoundSdkSourcemaps,
},
WebRendererMode.canvaskit: <NullSafetyMode, HostArtifact>{
NullSafetyMode.sound: HostArtifact.webPrecompiledDdcCanvaskitSoundSdkSourcemaps,
NullSafetyMode.unsound: HostArtifact.webPrecompiledDdcCanvaskitSdkSourcemaps,
NullSafetyMode.sound: HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSoundSdkSourcemaps,
},
WebRendererMode.html: <NullSafetyMode, HostArtifact>{
NullSafetyMode.sound: HostArtifact.webPrecompiledDdcSoundSdkSourcemaps,
NullSafetyMode.unsound: HostArtifact.webPrecompiledDdcSdkSourcemaps,
NullSafetyMode.sound: HostArtifact.webPrecompiledDdcLibraryBundleSoundSdkSourcemaps,
},
};

View File

@ -14,7 +14,7 @@ dependencies:
args: 2.6.0
browser_launcher: 1.1.3
dds: 4.2.7
dwds: 24.2.0
dwds: 24.3.0
completion: 1.0.1
coverage: 1.11.1
crypto: 3.0.6
@ -121,4 +121,4 @@ dartdoc:
# Exclude this package from the hosted API docs.
nodoc: true
# PUBSPEC CHECKSUM: 5640
# PUBSPEC CHECKSUM: 7741

View File

@ -59,12 +59,9 @@ void main() {
HostArtifact.webPrecompiledAmdCanvaskitSdk,
HostArtifact.webPrecompiledAmdSoundSdk,
HostArtifact.webPrecompiledAmdSdk,
HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSoundSdk,
HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdk,
HostArtifact.webPrecompiledDdcCanvaskitSoundSdk,
HostArtifact.webPrecompiledDdcCanvaskitSdk,
HostArtifact.webPrecompiledDdcSoundSdk,
HostArtifact.webPrecompiledDdcSdk,
HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitAndHtmlSoundSdk,
HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSoundSdk,
HostArtifact.webPrecompiledDdcLibraryBundleSoundSdk,
]) {
final File artifactFile = artifacts.getHostArtifact(artifact) as File;
artifactFile.createSync();
@ -123,7 +120,7 @@ void main() {
);
testUsingContext(
'FlutterWebPlatform serves the correct dart_sdk.js (ddc module system) for the passed web renderer',
'FlutterWebPlatform serves the correct dart_sdk.js (ddc library bundle module system) for the passed web renderer',
() async {
final ChromiumLauncher chromiumLauncher = ChromiumLauncher(
fileSystem: fileSystem,
@ -142,7 +139,7 @@ void main() {
'',
packageConfigPath: '.dart_tool/package_config.json',
treeShakeIcons: false,
extraFrontEndOptions: <String>['--dartdevc-module-format=ddc'],
extraFrontEndOptions: <String>['--dartdevc-module-format=ddc', '--canary'],
),
webMemoryFS: WebMemoryFS(),
fileSystem: fileSystem,
@ -164,7 +161,7 @@ void main() {
shelf.Request('GET', Uri.parse('http://localhost/dart_sdk.js')),
);
final String contents = await response.readAsString();
expect(contents, HostArtifact.webPrecompiledDdcCanvaskitSoundSdk.name);
expect(contents, HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSoundSdk.name);
await webPlatform.close();
},
overrides: <Type, Generator>{

View File

@ -270,40 +270,35 @@ void main() {
);
});
testWithoutContext('Precompiled web DDC module system artifact paths are correct', () {
testWithoutContext(
'Precompiled web DDC library bundle module system artifact paths are correct',
() {
expect(
artifacts.getHostArtifact(HostArtifact.webPrecompiledDdcSdk).path,
'root/bin/cache/flutter_web_sdk/kernel/ddc/dart_sdk.js',
artifacts.getHostArtifact(HostArtifact.webPrecompiledDdcLibraryBundleSoundSdk).path,
'root/bin/cache/flutter_web_sdk/kernel/ddcLibraryBundle-sound/dart_sdk.js',
);
expect(
artifacts.getHostArtifact(HostArtifact.webPrecompiledDdcSdkSourcemaps).path,
'root/bin/cache/flutter_web_sdk/kernel/ddc/dart_sdk.js.map',
artifacts
.getHostArtifact(HostArtifact.webPrecompiledDdcLibraryBundleSoundSdkSourcemaps)
.path,
'root/bin/cache/flutter_web_sdk/kernel/ddcLibraryBundle-sound/dart_sdk.js.map',
);
expect(
artifacts.getHostArtifact(HostArtifact.webPrecompiledDdcCanvaskitSdk).path,
'root/bin/cache/flutter_web_sdk/kernel/ddc-canvaskit/dart_sdk.js',
artifacts
.getHostArtifact(HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSoundSdk)
.path,
'root/bin/cache/flutter_web_sdk/kernel/ddcLibraryBundle-canvaskit-sound/dart_sdk.js',
);
expect(
artifacts.getHostArtifact(HostArtifact.webPrecompiledDdcCanvaskitSdkSourcemaps).path,
'root/bin/cache/flutter_web_sdk/kernel/ddc-canvaskit/dart_sdk.js.map',
artifacts
.getHostArtifact(
HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSoundSdkSourcemaps,
)
.path,
'root/bin/cache/flutter_web_sdk/kernel/ddcLibraryBundle-canvaskit-sound/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), 'android-arm');

View File

@ -177,9 +177,9 @@ void main() {
expect(result, contains("import 'org-dartlang-app:///bar_config.dart'"));
});
group('Using the DDC module system', () {
test('generateDDCBootstrapScript embeds urls correctly', () {
final String result = generateDDCBootstrapScript(
group('Using the DDC library bundle module system', () {
test('bootstrap script embeds urls correctly', () {
final String result = generateDDCLibraryBundleBootstrapScript(
entrypoint: 'foo/bar/main.js',
ddcModuleLoaderUrl: 'ddc_module_loader.js',
mapperUrl: 'mapper.js',
@ -196,8 +196,8 @@ void main() {
expect(result, contains('"id": "data-main"'));
});
test('generateDDCBootstrapScript initializes configuration objects', () {
final String result = generateDDCBootstrapScript(
test('bootstrap script initializes configuration objects', () {
final String result = generateDDCLibraryBundleBootstrapScript(
entrypoint: 'foo/bar/main.js',
ddcModuleLoaderUrl: 'ddc_module_loader.js',
mapperUrl: 'mapper.js',
@ -216,8 +216,8 @@ void main() {
expect(result, contains(r'window.$dartLoader.loader ='));
});
test('generateDDCBootstrapScript includes loading indicator', () {
final String result = generateDDCBootstrapScript(
test('bootstrap script includes loading indicator', () {
final String result = generateDDCLibraryBundleBootstrapScript(
entrypoint: 'foo/bar/main.js',
ddcModuleLoaderUrl: 'ddc_module_loader.js',
mapperUrl: 'mapper.js',
@ -227,8 +227,8 @@ void main() {
expect(result, contains('"indeterminate"'));
});
test('generateDDCBootstrapScript does not include loading indicator', () {
final String result = generateDDCBootstrapScript(
test('bootstrap script does not include loading indicator', () {
final String result = generateDDCLibraryBundleBootstrapScript(
entrypoint: 'foo/bar/main.js',
ddcModuleLoaderUrl: 'ddc_module_loader.js',
mapperUrl: 'mapper.js',
@ -239,8 +239,8 @@ void main() {
});
// https://github.com/flutter/flutter/issues/107742
test('generateDDCBootstrapScript loading indicator does not trigger scrollbars', () {
final String result = generateDDCBootstrapScript(
test('bootstrap script loading indicator does not trigger scrollbars', () {
final String result = generateDDCLibraryBundleBootstrapScript(
entrypoint: 'foo/bar/main.js',
ddcModuleLoaderUrl: 'ddc_module_loader.js',
mapperUrl: 'mapper.js',
@ -253,51 +253,37 @@ void main() {
expect(result, matches(regex), reason: '.flutter-loader must have overflow: hidden');
});
test('generateDDCMainModule embeds the entrypoint correctly', () {
final String result = generateDDCMainModule(
test('generateDDCLibraryBundleMainModule embeds the entrypoint correctly', () {
final String result = generateDDCLibraryBundleMainModule(
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");'));
expect(result, contains('let appName = "org-dartlang-app:/main.js";'));
expect(result, contains('dartDevEmbedder.runMain(appName, sdkOptions);'));
});
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(
test('generateDDCLibraryBundleMainModule includes null safety switches', () {
final String result = generateDDCLibraryBundleMainModule(
entrypoint: 'main.js',
nullAssertions: true,
nativeNullAssertions: true,
);
expect(result, contains('''dart.nonNullAsserts(true);'''));
expect(result, contains('''dart.nativeNonNullAsserts(true);'''));
expect(result, contains('nonNullAsserts: true'));
expect(result, contains('nativeNonNullAsserts: true'));
});
test('generateDDCMainModule can disable null safety switches', () {
final String result = generateDDCMainModule(
test('generateDDCLibraryBundleMainModule can disable null safety switches', () {
final String result = generateDDCLibraryBundleMainModule(
entrypoint: 'main.js',
nullAssertions: false,
nativeNullAssertions: false,
);
expect(result, contains('''dart.nonNullAsserts(false);'''));
expect(result, contains('''dart.nativeNonNullAsserts(false);'''));
expect(result, contains('nonNullAsserts: false'));
expect(result, contains('nativeNonNullAsserts: false'));
});
test('generateTestBootstrapFileContents embeds urls correctly', () {

View File

@ -51,6 +51,7 @@ void main() {
late FakeHttpServer httpServer;
late BufferLogger logger;
const bool usesDdcModuleSystem = true;
const bool canaryFeatures = true;
setUpAll(() async {
packages = PackageConfig(<Package>[
@ -73,6 +74,7 @@ void main() {
<String, String>{},
NullSafetyMode.unsound,
usesDdcModuleSystem,
canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
);
@ -318,6 +320,7 @@ void main() {
<String, String>{},
NullSafetyMode.unsound,
usesDdcModuleSystem,
canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
);
@ -338,6 +341,7 @@ void main() {
<String, String>{},
NullSafetyMode.unsound,
usesDdcModuleSystem,
canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
);
@ -361,6 +365,7 @@ void main() {
<String, String>{},
NullSafetyMode.unsound,
usesDdcModuleSystem,
canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
),
@ -383,6 +388,7 @@ void main() {
<String, String>{},
NullSafetyMode.unsound,
usesDdcModuleSystem,
canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
),
@ -766,126 +772,6 @@ void main() {
expect(httpServer.closed, true);
});
runInTestbed(
'Can start web server with specified DDC module system assets',
() async {
final String path = globals.fs.path.join('lib', 'main.dart');
final File outputFile = globals.fs.file(path)..createSync(recursive: true);
outputFile.parent.childFile('a.sources').writeAsStringSync('');
outputFile.parent.childFile('a.json').writeAsStringSync('{}');
outputFile.parent.childFile('a.map').writeAsStringSync('{}');
outputFile.parent.childFile('a.metadata').writeAsStringSync('{}');
final ResidentCompiler residentCompiler =
FakeResidentCompiler()..output = const CompilerOutput('a', 0, <Uri>[]);
final WebDevFS webDevFS = WebDevFS(
hostname: 'localhost',
port: 0,
tlsCertPath: null,
tlsCertKeyPath: null,
packagesFilePath: '.dart_tool/package_config.json',
urlTunneller: null,
useSseForDebugProxy: true,
useSseForDebugBackend: true,
useSseForInjectedClient: true,
nullAssertions: true,
nativeNullAssertions: true,
buildInfo: const BuildInfo(
BuildMode.debug,
'',
treeShakeIcons: false,
nullSafetyMode: NullSafetyMode.unsound,
packageConfigPath: '.dart_tool/package_config.json',
),
enableDwds: false,
enableDds: false,
entrypoint: Uri.base,
testMode: true,
expressionCompiler: null,
extraHeaders: const <String, String>{},
chromiumLauncher: null,
nullSafetyMode: NullSafetyMode.unsound,
ddcModuleSystem: usesDdcModuleSystem,
webRenderer: WebRendererMode.html,
isWasm: false,
useLocalCanvasKit: false,
rootDirectory: globals.fs.currentDirectory,
);
webDevFS.ddcModuleLoaderJS.createSync(recursive: true);
webDevFS.flutterJs.createSync(recursive: true);
webDevFS.stackTraceMapper.createSync(recursive: true);
final Uri uri = await webDevFS.create();
webDevFS.webAssetServer.entrypointCacheDirectory = globals.fs.currentDirectory;
final String webPrecompiledSdk =
globals.artifacts!.getHostArtifact(HostArtifact.webPrecompiledDdcSdk).path;
final String webPrecompiledSdkSourcemaps =
globals.artifacts!.getHostArtifact(HostArtifact.webPrecompiledDdcSdkSourcemaps).path;
final String webPrecompiledCanvaskitSdk =
globals.artifacts!.getHostArtifact(HostArtifact.webPrecompiledDdcCanvaskitSdk).path;
final String webPrecompiledCanvaskitSdkSourcemaps =
globals.artifacts!
.getHostArtifact(HostArtifact.webPrecompiledDdcCanvaskitSdkSourcemaps)
.path;
globals.fs.currentDirectory.childDirectory('lib').childFile('web_entrypoint.dart')
..createSync(recursive: true)
..writeAsStringSync('GENERATED');
globals.fs.file(webPrecompiledSdk)
..createSync(recursive: true)
..writeAsStringSync('HELLO');
globals.fs.file(webPrecompiledSdkSourcemaps)
..createSync(recursive: true)
..writeAsStringSync('THERE');
globals.fs.file(webPrecompiledCanvaskitSdk)
..createSync(recursive: true)
..writeAsStringSync('OL');
globals.fs.file(webPrecompiledCanvaskitSdkSourcemaps)
..createSync(recursive: true)
..writeAsStringSync('CHUM');
await webDevFS.update(
mainUri: globals.fs.file(globals.fs.path.join('lib', 'main.dart')).uri,
generator: residentCompiler,
trackWidgetCreation: true,
bundleFirstUpload: true,
invalidatedFiles: <Uri>[],
packageConfig: PackageConfig.empty,
pathToReload: '',
dillOutputPath: 'out.dill',
shaderCompiler: const FakeShaderCompiler(),
);
expect(webDevFS.webAssetServer.getFile('ddc_module_loader.js'), isNotNull);
expect(webDevFS.webAssetServer.getFile('stack_trace_mapper.js'), isNotNull);
expect(webDevFS.webAssetServer.getFile('main.dart'), isNotNull);
expect(webDevFS.webAssetServer.getFile('manifest.json'), isNotNull);
expect(webDevFS.webAssetServer.getFile('flutter.js'), isNotNull);
expect(webDevFS.webAssetServer.getFile('flutter_service_worker.js'), isNotNull);
expect(webDevFS.webAssetServer.getFile('version.json'), isNotNull);
expect(await webDevFS.webAssetServer.dartSourceContents('dart_sdk.js'), 'HELLO');
expect(await webDevFS.webAssetServer.dartSourceContents('dart_sdk.js.map'), 'THERE');
// Update to the SDK.
globals.fs.file(webPrecompiledSdk).writeAsStringSync('BELLOW');
// New SDK should be visible..
expect(await webDevFS.webAssetServer.dartSourceContents('dart_sdk.js'), 'BELLOW');
// Generated entrypoint.
expect(
await webDevFS.webAssetServer.dartSourceContents('web_entrypoint.dart'),
contains('GENERATED'),
);
// served on localhost
expect(uri.host, 'localhost');
await webDevFS.destroy();
},
overrides: <Type, Generator>{Artifacts: Artifacts.test},
);
runInTestbed(
'Can start web server with specified assets in sound null safety mode',
() async {
@ -926,6 +812,7 @@ void main() {
chromiumLauncher: null,
nullSafetyMode: NullSafetyMode.sound,
ddcModuleSystem: usesDdcModuleSystem,
canaryFeatures: canaryFeatures,
webRenderer: WebRendererMode.html,
isWasm: false,
useLocalCanvasKit: false,
@ -941,14 +828,22 @@ void main() {
..createSync(recursive: true)
..writeAsStringSync('GENERATED');
final String webPrecompiledSdk =
globals.artifacts!.getHostArtifact(HostArtifact.webPrecompiledDdcSoundSdk).path;
globals.artifacts!
.getHostArtifact(HostArtifact.webPrecompiledDdcLibraryBundleSoundSdk)
.path;
final String webPrecompiledSdkSourcemaps =
globals.artifacts!.getHostArtifact(HostArtifact.webPrecompiledDdcSoundSdkSourcemaps).path;
globals.artifacts!
.getHostArtifact(HostArtifact.webPrecompiledDdcLibraryBundleSoundSdkSourcemaps)
.path;
final String webPrecompiledCanvaskitSdk =
globals.artifacts!.getHostArtifact(HostArtifact.webPrecompiledDdcCanvaskitSoundSdk).path;
globals.artifacts!
.getHostArtifact(HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSoundSdk)
.path;
final String webPrecompiledCanvaskitSdkSourcemaps =
globals.artifacts!
.getHostArtifact(HostArtifact.webPrecompiledDdcCanvaskitSoundSdkSourcemaps)
.getHostArtifact(
HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSoundSdkSourcemaps,
)
.path;
globals.fs.file(webPrecompiledSdk)
..createSync(recursive: true)
@ -1044,6 +939,7 @@ void main() {
chromiumLauncher: null,
nullSafetyMode: NullSafetyMode.sound,
ddcModuleSystem: usesDdcModuleSystem,
canaryFeatures: canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
isWasm: false,
useLocalCanvasKit: false,
@ -1118,6 +1014,7 @@ void main() {
nativeNullAssertions: true,
nullSafetyMode: NullSafetyMode.sound,
ddcModuleSystem: usesDdcModuleSystem,
canaryFeatures: canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
isWasm: false,
useLocalCanvasKit: false,
@ -1167,6 +1064,7 @@ void main() {
chromiumLauncher: null,
nullSafetyMode: NullSafetyMode.sound,
ddcModuleSystem: usesDdcModuleSystem,
canaryFeatures: canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
isWasm: false,
useLocalCanvasKit: false,
@ -1217,6 +1115,7 @@ void main() {
chromiumLauncher: null,
nullSafetyMode: NullSafetyMode.sound,
ddcModuleSystem: usesDdcModuleSystem,
canaryFeatures: canaryFeatures,
webRenderer: WebRendererMode.auto,
isWasm: false,
useLocalCanvasKit: false,
@ -1267,6 +1166,7 @@ void main() {
chromiumLauncher: null,
nullSafetyMode: NullSafetyMode.unsound,
ddcModuleSystem: usesDdcModuleSystem,
canaryFeatures: canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
isWasm: false,
useLocalCanvasKit: false,
@ -1380,6 +1280,7 @@ void main() {
<String, String>{},
NullSafetyMode.sound,
usesDdcModuleSystem,
canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
);
@ -1429,6 +1330,7 @@ void main() {
chromiumLauncher: null,
nullSafetyMode: NullSafetyMode.unsound,
ddcModuleSystem: usesDdcModuleSystem,
canaryFeatures: canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
isWasm: false,
useLocalCanvasKit: false,

View File

@ -106,6 +106,7 @@ void main() {
late FakeHttpServer httpServer;
late BufferLogger logger;
const bool usesDdcModuleSystem = false;
const bool canaryFeatures = false;
setUpAll(() async {
packages = PackageConfig(<Package>[
@ -128,6 +129,7 @@ void main() {
<String, String>{},
NullSafetyMode.unsound,
usesDdcModuleSystem,
canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
);
@ -395,6 +397,7 @@ void main() {
<String, String>{},
NullSafetyMode.unsound,
usesDdcModuleSystem,
canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
);
@ -418,6 +421,7 @@ void main() {
<String, String>{},
NullSafetyMode.unsound,
usesDdcModuleSystem,
canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
);
@ -444,6 +448,7 @@ void main() {
<String, String>{},
NullSafetyMode.unsound,
usesDdcModuleSystem,
canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
),
@ -469,6 +474,7 @@ void main() {
<String, String>{},
NullSafetyMode.unsound,
usesDdcModuleSystem,
canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
),
@ -541,6 +547,7 @@ void main() {
<String, String>{},
NullSafetyMode.unsound,
usesDdcModuleSystem,
canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: true,
);
@ -983,6 +990,7 @@ void main() {
chromiumLauncher: null,
nullSafetyMode: NullSafetyMode.unsound,
ddcModuleSystem: usesDdcModuleSystem,
canaryFeatures: canaryFeatures,
webRenderer: WebRendererMode.html,
isWasm: false,
useLocalCanvasKit: false,
@ -1101,6 +1109,7 @@ void main() {
chromiumLauncher: null,
nullSafetyMode: NullSafetyMode.sound,
ddcModuleSystem: usesDdcModuleSystem,
canaryFeatures: canaryFeatures,
webRenderer: WebRendererMode.html,
isWasm: false,
useLocalCanvasKit: false,
@ -1225,6 +1234,7 @@ void main() {
chromiumLauncher: null,
nullSafetyMode: NullSafetyMode.sound,
ddcModuleSystem: usesDdcModuleSystem,
canaryFeatures: canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
isWasm: false,
useLocalCanvasKit: false,
@ -1302,6 +1312,7 @@ void main() {
nativeNullAssertions: true,
nullSafetyMode: NullSafetyMode.sound,
ddcModuleSystem: usesDdcModuleSystem,
canaryFeatures: canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
isWasm: false,
useLocalCanvasKit: false,
@ -1354,6 +1365,7 @@ void main() {
chromiumLauncher: null,
nullSafetyMode: NullSafetyMode.sound,
ddcModuleSystem: usesDdcModuleSystem,
canaryFeatures: canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
isWasm: false,
useLocalCanvasKit: false,
@ -1407,6 +1419,7 @@ void main() {
chromiumLauncher: null,
nullSafetyMode: NullSafetyMode.sound,
ddcModuleSystem: usesDdcModuleSystem,
canaryFeatures: canaryFeatures,
webRenderer: WebRendererMode.auto,
isWasm: false,
useLocalCanvasKit: false,
@ -1460,6 +1473,7 @@ void main() {
chromiumLauncher: null,
nullSafetyMode: NullSafetyMode.unsound,
ddcModuleSystem: usesDdcModuleSystem,
canaryFeatures: canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
isWasm: false,
useLocalCanvasKit: false,
@ -1582,6 +1596,7 @@ void main() {
<String, String>{},
NullSafetyMode.sound,
usesDdcModuleSystem,
canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
useLocalCanvasKit: false,
);
@ -1632,6 +1647,7 @@ void main() {
chromiumLauncher: null,
nullSafetyMode: NullSafetyMode.unsound,
ddcModuleSystem: usesDdcModuleSystem,
canaryFeatures: canaryFeatures,
webRenderer: WebRendererMode.canvaskit,
isWasm: false,
useLocalCanvasKit: false,