diff --git a/engine/src/flutter/web_sdk/BUILD.gn b/engine/src/flutter/web_sdk/BUILD.gn index 704c1aa7e0..925d6fac45 100644 --- a/engine/src/flutter/web_sdk/BUILD.gn +++ b/engine/src/flutter/web_sdk/BUILD.gn @@ -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 += diff --git a/packages/flutter_tools/lib/src/artifacts.dart b/packages/flutter_tools/lib/src/artifacts.dart index 0c9239e5d4..d665e5af86 100644 --- a/packages/flutter_tools/lib/src/artifacts.dart +++ b/packages/flutter_tools/lib/src/artifacts.dart @@ -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); diff --git a/packages/flutter_tools/lib/src/build_info.dart b/packages/flutter_tools/lib/src/build_info.dart index fde25bf117..88f46b73e2 100644 --- a/packages/flutter_tools/lib/src/build_info.dart +++ b/packages/flutter_tools/lib/src/build_info.dart @@ -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? 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); +({DdcModuleFormat? ddcModuleFormat, bool? canaryFeatures}) +_ddcModuleFormatAndCanaryFeaturesFromFrontEndArgs(List? 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(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() { diff --git a/packages/flutter_tools/lib/src/isolated/devfs_web.dart b/packages/flutter_tools/lib/src/isolated/devfs_web.dart index 801e01eb89..d41853a01f 100644 --- a/packages/flutter_tools/lib/src/isolated/devfs_web.dart +++ b/packages/flutter_tools/lib/src/isolated/devfs_web.dart @@ -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> 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> 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 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, diff --git a/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart b/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart index 0ee93d6d05..f7d1288499 100644 --- a/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart +++ b/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart @@ -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, diff --git a/packages/flutter_tools/lib/src/test/flutter_web_platform.dart b/packages/flutter_tools/lib/src/test/flutter_web_platform.dart index 6e711fb2aa..57c50b6cc7 100644 --- a/packages/flutter_tools/lib/src/test/flutter_web_platform.dart +++ b/packages/flutter_tools/lib/src/test/flutter_web_platform.dart @@ -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> 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> dartSdkArtifactMap = buildInfo.ddcModuleFormat == DdcModuleFormat.ddc - ? kDdcDartSdkJsMapArtifactMap + ? kDdcLibraryBundleDartSdkJsMapArtifactMap : kAmdDartSdkJsMapArtifactMap; return _fileSystem.file( _artifacts!.getHostArtifact(dartSdkArtifactMap[webRenderer]![_nullSafetyMode]!), diff --git a/packages/flutter_tools/lib/src/web/bootstrap.dart b/packages/flutter_tools/lib/src/web/bootstrap.dart index 4351b01227..633b7ed06d 100644 --- a/packages/flutter_tools/lib/src/web/bootstrap.dart +++ b/packages/flutter_tools/lib/src/web/bootstrap.dart @@ -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. /// diff --git a/packages/flutter_tools/lib/src/web/compile.dart b/packages/flutter_tools/lib/src/web/compile.dart index 68fb4a3f13..c7c7aef321 100644 --- a/packages/flutter_tools/lib/src/web/compile.dart +++ b/packages/flutter_tools/lib/src/web/compile.dart @@ -296,39 +296,38 @@ const Map> kAmdDartSdkJsMapAr }, }; -/// The correct precompiled artifact to use for each build and render mode for DDC with DDC modules. -const Map> kDdcDartSdkJsArtifactMap = - >{ - WebRendererMode.auto: { - NullSafetyMode.sound: HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSoundSdk, - NullSafetyMode.unsound: HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdk, - }, - WebRendererMode.canvaskit: { - NullSafetyMode.sound: HostArtifact.webPrecompiledDdcCanvaskitSoundSdk, - NullSafetyMode.unsound: HostArtifact.webPrecompiledDdcCanvaskitSdk, - }, - WebRendererMode.html: { - NullSafetyMode.sound: HostArtifact.webPrecompiledDdcSoundSdk, - NullSafetyMode.unsound: HostArtifact.webPrecompiledDdcSdk, - }, - }; +/// 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> +kDdcLibraryBundleDartSdkJsArtifactMap = >{ + WebRendererMode.auto: { + NullSafetyMode.sound: HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitAndHtmlSoundSdk, + }, + WebRendererMode.canvaskit: { + NullSafetyMode.sound: HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSoundSdk, + }, + WebRendererMode.html: { + NullSafetyMode.sound: HostArtifact.webPrecompiledDdcLibraryBundleSoundSdk, + }, +}; -/// The correct source map artifact to use for each build and render mode for DDC with DDC modules. -const Map> kDdcDartSdkJsMapArtifactMap = - >{ - WebRendererMode.auto: { - NullSafetyMode.sound: HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSoundSdkSourcemaps, - NullSafetyMode.unsound: HostArtifact.webPrecompiledDdcCanvaskitAndHtmlSdkSourcemaps, - }, - WebRendererMode.canvaskit: { - NullSafetyMode.sound: HostArtifact.webPrecompiledDdcCanvaskitSoundSdkSourcemaps, - NullSafetyMode.unsound: HostArtifact.webPrecompiledDdcCanvaskitSdkSourcemaps, - }, - WebRendererMode.html: { - NullSafetyMode.sound: HostArtifact.webPrecompiledDdcSoundSdkSourcemaps, - NullSafetyMode.unsound: HostArtifact.webPrecompiledDdcSdkSourcemaps, - }, - }; +/// 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> +kDdcLibraryBundleDartSdkJsMapArtifactMap = >{ + WebRendererMode.auto: { + NullSafetyMode.sound: + HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitAndHtmlSoundSdkSourcemaps, + }, + WebRendererMode.canvaskit: { + NullSafetyMode.sound: HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSoundSdkSourcemaps, + }, + WebRendererMode.html: { + NullSafetyMode.sound: HostArtifact.webPrecompiledDdcLibraryBundleSoundSdkSourcemaps, + }, +}; String _buildEventAnalyticsSettings({required List configs}) { final Map values = {}; diff --git a/packages/flutter_tools/pubspec.yaml b/packages/flutter_tools/pubspec.yaml index ce33adee7a..bb460b6a7e 100644 --- a/packages/flutter_tools/pubspec.yaml +++ b/packages/flutter_tools/pubspec.yaml @@ -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 diff --git a/packages/flutter_tools/test/commands.shard/hermetic/flutter_web_platform_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/flutter_web_platform_test.dart index cb0533c25e..101d3380b8 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/flutter_web_platform_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/flutter_web_platform_test.dart @@ -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: ['--dartdevc-module-format=ddc'], + extraFrontEndOptions: ['--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: { diff --git a/packages/flutter_tools/test/general.shard/artifacts_test.dart b/packages/flutter_tools/test/general.shard/artifacts_test.dart index d3b02aacef..6addc3942a 100644 --- a/packages/flutter_tools/test/general.shard/artifacts_test.dart +++ b/packages/flutter_tools/test/general.shard/artifacts_test.dart @@ -270,40 +270,35 @@ void main() { ); }); - 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( + 'Precompiled web DDC library bundle module system artifact paths are correct', + () { + expect( + artifacts.getHostArtifact(HostArtifact.webPrecompiledDdcLibraryBundleSoundSdk).path, + 'root/bin/cache/flutter_web_sdk/kernel/ddcLibraryBundle-sound/dart_sdk.js', + ); + expect( + artifacts + .getHostArtifact(HostArtifact.webPrecompiledDdcLibraryBundleSoundSdkSourcemaps) + .path, + 'root/bin/cache/flutter_web_sdk/kernel/ddcLibraryBundle-sound/dart_sdk.js.map', + ); + expect( + artifacts + .getHostArtifact(HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSoundSdk) + .path, + 'root/bin/cache/flutter_web_sdk/kernel/ddcLibraryBundle-canvaskit-sound/dart_sdk.js', + ); + expect( + artifacts + .getHostArtifact( + HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSoundSdkSourcemaps, + ) + .path, + 'root/bin/cache/flutter_web_sdk/kernel/ddcLibraryBundle-canvaskit-sound/dart_sdk.js.map', + ); + }, + ); testWithoutContext('getEngineType', () { expect(artifacts.getEngineType(TargetPlatform.android_arm, BuildMode.debug), 'android-arm'); diff --git a/packages/flutter_tools/test/general.shard/web/bootstrap_test.dart b/packages/flutter_tools/test/general.shard/web/bootstrap_test.dart index aa9f3e8fb9..6b31f0b720 100644 --- a/packages/flutter_tools/test/general.shard/web/bootstrap_test.dart +++ b/packages/flutter_tools/test/general.shard/web/bootstrap_test.dart @@ -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', () { diff --git a/packages/flutter_tools/test/general.shard/web/devfs_web_ddc_modules_test.dart b/packages/flutter_tools/test/general.shard/web/devfs_web_ddc_modules_test.dart index b583c7e670..cecd1ad062 100644 --- a/packages/flutter_tools/test/general.shard/web/devfs_web_ddc_modules_test.dart +++ b/packages/flutter_tools/test/general.shard/web/devfs_web_ddc_modules_test.dart @@ -51,6 +51,7 @@ void main() { late FakeHttpServer httpServer; late BufferLogger logger; const bool usesDdcModuleSystem = true; + const bool canaryFeatures = true; setUpAll(() async { packages = PackageConfig([ @@ -73,6 +74,7 @@ void main() { {}, NullSafetyMode.unsound, usesDdcModuleSystem, + canaryFeatures, webRenderer: WebRendererMode.canvaskit, useLocalCanvasKit: false, ); @@ -318,6 +320,7 @@ void main() { {}, NullSafetyMode.unsound, usesDdcModuleSystem, + canaryFeatures, webRenderer: WebRendererMode.canvaskit, useLocalCanvasKit: false, ); @@ -338,6 +341,7 @@ void main() { {}, NullSafetyMode.unsound, usesDdcModuleSystem, + canaryFeatures, webRenderer: WebRendererMode.canvaskit, useLocalCanvasKit: false, ); @@ -361,6 +365,7 @@ void main() { {}, NullSafetyMode.unsound, usesDdcModuleSystem, + canaryFeatures, webRenderer: WebRendererMode.canvaskit, useLocalCanvasKit: false, ), @@ -383,6 +388,7 @@ void main() { {}, 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, []); - - 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 {}, - 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: [], - 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: {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() { {}, 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, diff --git a/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart b/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart index 2e868d4bf3..cc6f6724bf 100644 --- a/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart +++ b/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart @@ -106,6 +106,7 @@ void main() { late FakeHttpServer httpServer; late BufferLogger logger; const bool usesDdcModuleSystem = false; + const bool canaryFeatures = false; setUpAll(() async { packages = PackageConfig([ @@ -128,6 +129,7 @@ void main() { {}, NullSafetyMode.unsound, usesDdcModuleSystem, + canaryFeatures, webRenderer: WebRendererMode.canvaskit, useLocalCanvasKit: false, ); @@ -395,6 +397,7 @@ void main() { {}, NullSafetyMode.unsound, usesDdcModuleSystem, + canaryFeatures, webRenderer: WebRendererMode.canvaskit, useLocalCanvasKit: false, ); @@ -418,6 +421,7 @@ void main() { {}, NullSafetyMode.unsound, usesDdcModuleSystem, + canaryFeatures, webRenderer: WebRendererMode.canvaskit, useLocalCanvasKit: false, ); @@ -444,6 +448,7 @@ void main() { {}, NullSafetyMode.unsound, usesDdcModuleSystem, + canaryFeatures, webRenderer: WebRendererMode.canvaskit, useLocalCanvasKit: false, ), @@ -469,6 +474,7 @@ void main() { {}, NullSafetyMode.unsound, usesDdcModuleSystem, + canaryFeatures, webRenderer: WebRendererMode.canvaskit, useLocalCanvasKit: false, ), @@ -541,6 +547,7 @@ void main() { {}, 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() { {}, 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,