From 76d0e5035184dd35ab226d838a8a2a10bab72761 Mon Sep 17 00:00:00 2001 From: Kilian Schulte Date: Thu, 4 Dec 2025 17:08:15 +0100 Subject: [PATCH 1/8] add custom sdk build options --- build_web_compilers/lib/builders.dart | 113 +++++++++++++++--- .../lib/src/dart2js_bootstrap.dart | 11 +- .../lib/src/dart2wasm_bootstrap.dart | 13 +- .../lib/src/dev_compiler_bootstrap.dart | 11 +- build_web_compilers/lib/src/platforms.dart | 35 ++++-- .../lib/src/sdk_js_compile_builder.dart | 60 ++++++++-- .../lib/src/web_entrypoint_builder.dart | 31 +++++ 7 files changed, 230 insertions(+), 44 deletions(-) diff --git a/build_web_compilers/lib/builders.dart b/build_web_compilers/lib/builders.dart index f11ddac3e8..3122614d1c 100644 --- a/build_web_compilers/lib/builders.dart +++ b/build_web_compilers/lib/builders.dart @@ -9,17 +9,20 @@ import 'package:collection/collection.dart'; import 'build_web_compilers.dart'; import 'src/common.dart'; import 'src/ddc_frontend_server_builder.dart'; +import 'src/platforms.dart'; import 'src/sdk_js_compile_builder.dart'; import 'src/sdk_js_copy_builder.dart'; import 'src/web_entrypoint_marker_builder.dart'; // Shared entrypoint builder Builder webEntrypointBuilder(BuilderOptions options) { + _ensureSamePlatformOptions(options); _ensureSameDdcHotReloadOptions(options); return WebEntrypointBuilder.fromOptions(options); } Builder webEntrypointMarkerBuilder(BuilderOptions options) { + _ensureSamePlatformOptions(options); _ensureSameDdcHotReloadOptions(options); return WebEntrypointMarkerBuilder( usesWebHotReload: _readWebHotReloadOption(options), @@ -28,16 +31,19 @@ Builder webEntrypointMarkerBuilder(BuilderOptions options) { // DDC related builders Builder ddcMetaModuleBuilder(BuilderOptions options) { + _ensureSamePlatformOptions(options); _ensureSameDdcHotReloadOptions(options); return MetaModuleBuilder.forOptions(ddcPlatform, options); } Builder ddcMetaModuleCleanBuilder(BuilderOptions options) { + _ensureSamePlatformOptions(options); _ensureSameDdcHotReloadOptions(options); return MetaModuleCleanBuilder(ddcPlatform); } Builder ddcModuleBuilder(BuilderOptions options) { + _ensureSamePlatformOptions(options); _ensureSameDdcHotReloadOptions(options); return ModuleBuilder( ddcPlatform, @@ -47,6 +53,7 @@ Builder ddcModuleBuilder(BuilderOptions options) { Builder ddcBuilder(BuilderOptions options) { validateOptions(options.config, _supportedOptions, 'build_web_compilers:ddc'); + _ensureSamePlatformOptions(options); _ensureSameDdcHotReloadOptions(options); _ensureSameDdcOptions(options); @@ -60,9 +67,11 @@ Builder ddcBuilder(BuilderOptions options) { emitDebugSymbols: _readEmitDebugSymbolsOption(options), canaryFeatures: _readCanaryOption(options), ddcModules: _readWebHotReloadOption(options), - sdkKernelPath: sdkDdcKernelPath, trackUnusedInputs: _readTrackInputsCompilerOption(options), platform: ddcPlatform, + sdkKernelPath: _readDdcKernelPathOption(options), + librariesPath: _readLibrariesPathOption(options), + platformSdk: _readPlatformSdkOption(options), environment: _readEnvironmentOption(options), ); } @@ -71,16 +80,19 @@ final ddcKernelExtension = '.ddc.dill'; Builder ddcKernelBuilder(BuilderOptions options) { validateOptions(options.config, _supportedOptions, 'build_web_compilers:ddc'); + _ensureSamePlatformOptions(options); _ensureSameDdcHotReloadOptions(options); _ensureSameDdcOptions(options); return KernelBuilder( summaryOnly: true, - sdkKernelPath: sdkDdcKernelPath, + sdkKernelPath: _readDdcKernelPathOption(options), outputExtension: ddcKernelExtension, platform: ddcPlatform, + librariesPath: _readLibrariesPathOption(options), useIncrementalCompiler: _readUseIncrementalCompilerOption(options), trackUnusedInputs: _readTrackInputsCompilerOption(options), + platformSdk: _readPlatformSdkOption(options), ); } @@ -93,26 +105,44 @@ Builder sdkJsCompile(BuilderOptions options) { canaryFeatures: _readWebHotReloadOption(options) || _readCanaryOption(options), usesWebHotReload: _readWebHotReloadOption(options), + usePrebuiltSdkFromPath: _readUsePrebuiltSdkFromPathOption(options), ); } // Dart2js related builders -Builder dart2jsMetaModuleBuilder(BuilderOptions options) => - MetaModuleBuilder.forOptions(dart2jsPlatform, options); -Builder dart2jsMetaModuleCleanBuilder(BuilderOptions _) => - MetaModuleCleanBuilder(dart2jsPlatform); -Builder dart2jsModuleBuilder(BuilderOptions _) => - ModuleBuilder(dart2jsPlatform); +Builder dart2jsMetaModuleBuilder(BuilderOptions options) { + _ensureSamePlatformOptions(options); + return MetaModuleBuilder.forOptions(dart2jsPlatform, options); +} + +Builder dart2jsMetaModuleCleanBuilder(BuilderOptions options) { + _ensureSamePlatformOptions(options); + return MetaModuleCleanBuilder(dart2jsPlatform); +} + +Builder dart2jsModuleBuilder(BuilderOptions options) { + _ensureSamePlatformOptions(options); + return ModuleBuilder(dart2jsPlatform); +} + PostProcessBuilder dart2jsArchiveExtractor(BuilderOptions options) => Dart2JsArchiveExtractor.fromOptions(options); // Dart2wasm related builders -Builder dart2wasmMetaModuleBuilder(BuilderOptions options) => - MetaModuleBuilder.forOptions(dart2wasmPlatform, options); -Builder dart2wasmMetaModuleCleanBuilder(BuilderOptions _) => - MetaModuleCleanBuilder(dart2wasmPlatform); -Builder dart2wasmModuleBuilder(BuilderOptions _) => - ModuleBuilder(dart2wasmPlatform); +Builder dart2wasmMetaModuleBuilder(BuilderOptions options) { + _ensureSamePlatformOptions(options); + return MetaModuleBuilder.forOptions(dart2wasmPlatform, options); +} + +Builder dart2wasmMetaModuleCleanBuilder(BuilderOptions options) { + _ensureSamePlatformOptions(options); + return MetaModuleCleanBuilder(dart2wasmPlatform); +} + +Builder dart2wasmModuleBuilder(BuilderOptions options) { + _ensureSamePlatformOptions(options); + return ModuleBuilder(dart2wasmPlatform); +} // General purpose builders PostProcessBuilder dartSourceCleanup(BuilderOptions options) => @@ -170,6 +200,29 @@ void _ensureSameDdcHotReloadOptions(BuilderOptions options) { } } +void _ensureSamePlatformOptions(BuilderOptions options) { + final additionalCoreLibraries = _readAdditionalCoreLibrariesOption(options); + if (_lastAdditionalCoreLibraries == null) { + initializePlatforms(additionalCoreLibraries); + _lastAdditionalCoreLibraries = additionalCoreLibraries; + } else if (!const ListEquality().equals( + _lastAdditionalCoreLibraries, + additionalCoreLibraries, + )) { + throw ArgumentError( + '`additional-core-libraries` must be configured the same across the ' + 'following builders: build_web_compilers:ddc, ' + 'build_web_compilers|entrypoint, ' + 'build_web_compilers|entrypoint_marker, ' + 'build_web_compilers|ddc_modules, ' + 'build_web_compilers|dart2js_modules, ' + 'build_web_compilers|dart2wasm_modules.' + '\n\nPlease use the `global_options` section in ' + '`build.yaml` or the `--define` flag to set global options.', + ); + } +} + bool _readUseIncrementalCompilerOption(BuilderOptions options) { return options.config[_useIncrementalCompilerOption] as bool? ?? true; } @@ -194,6 +247,28 @@ bool _readWebHotReloadOption(BuilderOptions options) { return options.config[_webHotReloadOption] as bool? ?? false; } +List _readAdditionalCoreLibrariesOption(BuilderOptions options) { + return (options.config[_additionalCoreLibrariesOption] as List?) + ?.cast() ?? + []; +} + +String _readDdcKernelPathOption(BuilderOptions options) { + return options.config[_ddcKernelPathOption] as String? ?? sdkDdcKernelPath; +} + +String? _readLibrariesPathOption(BuilderOptions options) { + return options.config[_librariesPathOption] as String?; +} + +String? _readPlatformSdkOption(BuilderOptions options) { + return options.config[_platformSdkOption] as String?; +} + +String? _readUsePrebuiltSdkFromPathOption(BuilderOptions options) { + return options.config[_usePrebuiltSdkFromPathOption] as String?; +} + Map _readEnvironmentOption(BuilderOptions options) { final environment = options.config[_environmentOption] as Map? ?? const {}; return environment.map((key, value) => MapEntry('$key', '$value')); @@ -201,6 +276,7 @@ Map _readEnvironmentOption(BuilderOptions options) { Map? _previousDdcConfig; bool? _lastWebHotReloadValue; +List? _lastAdditionalCoreLibraries; const _useIncrementalCompilerOption = 'use-incremental-compiler'; const _generateFullDillOption = 'generate-full-dill'; const _emitDebugSymbolsOption = 'emit-debug-symbols'; @@ -208,6 +284,11 @@ const _canaryOption = 'canary'; const _trackUnusedInputsCompilerOption = 'track-unused-inputs'; const _environmentOption = 'environment'; const _webHotReloadOption = 'web-hot-reload'; +const _additionalCoreLibrariesOption = 'additional-core-libraries'; +const _ddcKernelPathOption = 'ddc-kernel-path'; +const _librariesPathOption = 'libraries-path'; +const _platformSdkOption = 'platform-sdk'; +const _usePrebuiltSdkFromPathOption = 'use-prebuilt-sdk-from-path'; const _supportedOptions = [ _environmentOption, @@ -217,4 +298,8 @@ const _supportedOptions = [ _canaryOption, _trackUnusedInputsCompilerOption, _webHotReloadOption, + _additionalCoreLibrariesOption, + _ddcKernelPathOption, + _librariesPathOption, + _platformSdkOption, ]; diff --git a/build_web_compilers/lib/src/dart2js_bootstrap.dart b/build_web_compilers/lib/src/dart2js_bootstrap.dart index f3c431578a..70a0a00c6d 100644 --- a/build_web_compilers/lib/src/dart2js_bootstrap.dart +++ b/build_web_compilers/lib/src/dart2js_bootstrap.dart @@ -28,6 +28,8 @@ Future bootstrapDart2Js( required bool? nativeNullAssertions, required bool onlyCompiler, String entrypointExtension = jsEntrypointExtension, + String? librariesPath, + bool silenceUnsupportedModulesWarnings = false, }) => _resourcePool.withResource( () => _bootstrapDart2Js( buildStep, @@ -35,6 +37,8 @@ Future bootstrapDart2Js( nativeNullAssertions: nativeNullAssertions, onlyCompiler: onlyCompiler, entrypointExtension: entrypointExtension, + librariesPath: librariesPath, + silenceUnsupportedModulesWarnings: silenceUnsupportedModulesWarnings, ), ); @@ -44,6 +48,8 @@ Future _bootstrapDart2Js( required bool? nativeNullAssertions, required bool onlyCompiler, required String entrypointExtension, + String? librariesPath, + bool silenceUnsupportedModulesWarnings = false, }) async { final dartEntrypointId = buildStep.inputId; final moduleId = dartEntrypointId.changeExtension( @@ -59,7 +65,7 @@ Future _bootstrapDart2Js( try { allDeps = (await module.computeTransitiveDependencies( buildStep, - throwIfUnsupported: true, + throwIfUnsupported: !silenceUnsupportedModulesWarnings, ))..add(module); } on UnsupportedModules catch (e) { final librariesString = (await e.exactLibraries(buildStep).toList()) @@ -97,7 +103,8 @@ $librariesString : dartUri.path.substring(1), ) + entrypointExtension; - final librariesSpec = p.joinAll([sdkDir, 'lib', 'libraries.json']); + final librariesSpec = + librariesPath ?? p.joinAll([sdkDir, 'lib', 'libraries.json']); _validateUserArgs(dart2JsArgs); args = dart2JsArgs.toList()..addAll([ diff --git a/build_web_compilers/lib/src/dart2wasm_bootstrap.dart b/build_web_compilers/lib/src/dart2wasm_bootstrap.dart index 690e0f7696..be28f8620d 100644 --- a/build_web_compilers/lib/src/dart2wasm_bootstrap.dart +++ b/build_web_compilers/lib/src/dart2wasm_bootstrap.dart @@ -45,13 +45,15 @@ final class Dart2WasmBootstrapResult { Future bootstrapDart2Wasm( BuildStep buildStep, List additionalArguments, - String javaScriptModuleExtension, -) async { + String javaScriptModuleExtension, { + bool silenceUnsupportedModulesWarnings = false, +}) async { return await _resourcePool.withResource( () => _bootstrapDart2Wasm( buildStep, additionalArguments, javaScriptModuleExtension, + silenceUnsupportedModulesWarnings: silenceUnsupportedModulesWarnings, ), ); } @@ -59,8 +61,9 @@ Future bootstrapDart2Wasm( Future _bootstrapDart2Wasm( BuildStep buildStep, List additionalArguments, - String javaScriptModuleExtension, -) async { + String javaScriptModuleExtension, { + bool silenceUnsupportedModulesWarnings = false, +}) async { final dartEntrypointId = buildStep.inputId; final moduleId = dartEntrypointId.changeExtension( moduleExtension(dart2wasmPlatform), @@ -75,7 +78,7 @@ Future _bootstrapDart2Wasm( try { allDeps = (await module.computeTransitiveDependencies( buildStep, - throwIfUnsupported: true, + throwIfUnsupported: !silenceUnsupportedModulesWarnings, ))..add(module); } on UnsupportedModules catch (e) { final librariesString = (await e.exactLibraries(buildStep).toList()) diff --git a/build_web_compilers/lib/src/dev_compiler_bootstrap.dart b/build_web_compilers/lib/src/dev_compiler_bootstrap.dart index bb71c44f94..eb3ccefa22 100644 --- a/build_web_compilers/lib/src/dev_compiler_bootstrap.dart +++ b/build_web_compilers/lib/src/dev_compiler_bootstrap.dart @@ -33,18 +33,19 @@ final stackTraceMapperPath = /// available to the app by making them inputs of this build action. Future bootstrapDdc( BuildStep buildStep, { - DartPlatform? platform, Iterable requiredAssets = const [], String entrypointExtension = jsEntrypointExtension, required bool? nativeNullAssertions, bool usesWebHotReload = false, + bool silenceUnsupportedModulesWarnings = false, }) async { - platform = ddcPlatform; // Ensures that the sdk resources are built and available. await _ensureResources(buildStep, requiredAssets); final dartEntrypointId = buildStep.inputId; - final moduleId = buildStep.inputId.changeExtension(moduleExtension(platform)); + final moduleId = buildStep.inputId.changeExtension( + moduleExtension(ddcPlatform), + ); final module = Module.fromJson( json.decode(await buildStep.readAsString(moduleId)) as Map, ); @@ -56,6 +57,7 @@ Future bootstrapDdc( module, buildStep, computeStronglyConnectedComponents: !usesWebHotReload, + throwIfUnsupported: !silenceUnsupportedModulesWarnings, ); } on UnsupportedModules catch (e) { final librariesString = (await e.exactLibraries(buildStep).toList()) @@ -251,11 +253,12 @@ Future> _ensureTransitiveJsModules( Module module, BuildStep buildStep, { bool computeStronglyConnectedComponents = true, + bool throwIfUnsupported = true, }) async { // Collect all the modules this module depends on, plus this module. final transitiveDeps = await module.computeTransitiveDependencies( buildStep, - throwIfUnsupported: true, + throwIfUnsupported: throwIfUnsupported, computeStronglyConnectedComponents: computeStronglyConnectedComponents, ); diff --git a/build_web_compilers/lib/src/platforms.dart b/build_web_compilers/lib/src/platforms.dart index e99446e523..d6b9959d89 100644 --- a/build_web_compilers/lib/src/platforms.dart +++ b/build_web_compilers/lib/src/platforms.dart @@ -24,7 +24,6 @@ const _coreLibraries = [ /// Additional libraries supported by both ddc and dart2js. const _additionalWebLibraries = [ - 'html', 'html', 'html_common', 'indexed_db', @@ -37,13 +36,29 @@ const _additionalWebLibraries = [ /// Additional libraries supported by dart2wasm. const _additionalWasmLibraries = ['ffi']; -const _jsCompilerLibraries = [..._coreLibraries, ..._additionalWebLibraries]; - -final ddcPlatform = DartPlatform.register('ddc', _jsCompilerLibraries); - -final dart2jsPlatform = DartPlatform.register('dart2js', _jsCompilerLibraries); +// These intentionally throw if [initializePlatforms] wasn't called first. +final ddcPlatform = DartPlatform.byName('ddc'); +final dart2jsPlatform = DartPlatform.byName('dart2js'); +final dart2wasmPlatform = DartPlatform.byName('dart2wasm'); -final dart2wasmPlatform = DartPlatform.register('dart2wasm', [ - ..._coreLibraries, - ..._additionalWasmLibraries, -]); +/// Registers the platforms with [DartPlatform]. +/// +/// Must be called before [ddcPlatform], [dart2jsPlatform], or +/// [dart2wasmPlatform] is used. +void initializePlatforms([List additionalCoreLibraries = const []]) { + DartPlatform.register('ddc', [ + ..._coreLibraries, + ..._additionalWebLibraries, + ...additionalCoreLibraries, + ]); + DartPlatform.register('dart2js', [ + ..._coreLibraries, + ..._additionalWebLibraries, + ...additionalCoreLibraries, + ]); + DartPlatform.register('dart2wasm', [ + ..._coreLibraries, + ..._additionalWasmLibraries, + ...additionalCoreLibraries, + ]); +} diff --git a/build_web_compilers/lib/src/sdk_js_compile_builder.dart b/build_web_compilers/lib/src/sdk_js_compile_builder.dart index 824fc89836..fe2b9e0372 100644 --- a/build_web_compilers/lib/src/sdk_js_compile_builder.dart +++ b/build_web_compilers/lib/src/sdk_js_compile_builder.dart @@ -46,6 +46,12 @@ class SdkJsCompileBuilder implements Builder { /// reload. final bool usesWebHotReload; + /// An optional directory path that contains prebuilt sdk files. + /// + /// If provided, skips compilation and copies the sdk and + /// source map files to the output. + final String? usePrebuiltSdkFromPath; + SdkJsCompileBuilder({ required this.sdkKernelPath, required String outputPath, @@ -53,6 +59,7 @@ class SdkJsCompileBuilder implements Builder { String? platformSdk, required this.canaryFeatures, required this.usesWebHotReload, + this.usePrebuiltSdkFromPath, }) : platformSdk = platformSdk ?? sdkDir, librariesPath = librariesPath ?? @@ -70,15 +77,19 @@ class SdkJsCompileBuilder implements Builder { @override Future build(BuildStep buildStep) async { - await _createDevCompilerModule( - buildStep, - platformSdk, - sdkKernelPath, - librariesPath, - jsOutputId, - canaryFeatures, - usesWebHotReload, - ); + if (usePrebuiltSdkFromPath case final String sdkPath) { + await _copyPrebuiltSdk(buildStep, sdkPath, jsOutputId); + } else { + await _createDevCompilerModule( + buildStep, + platformSdk, + sdkKernelPath, + librariesPath, + jsOutputId, + canaryFeatures, + usesWebHotReload, + ); + } } } @@ -152,3 +163,34 @@ Future _createDevCompilerModule( buildStep, ); } + +/// Copy the prebuilt SDK to the output. +Future _copyPrebuiltSdk( + BuildStep buildStep, + String sdkPath, + AssetId jsOutputId, +) async { + final sdkFile = File(p.join(sdkPath, 'dart_sdk.js')); + if (!sdkFile.existsSync()) { + throw ArgumentError( + 'Prebuilt SDK file "dart_sdk.js" ' + 'does not exist at $sdkPath', + ); + } + + await buildStep.writeAsBytes(jsOutputId, await sdkFile.readAsBytes()); + + final sourceMapFile = File(p.join(sdkPath, 'dart_sdk.js.map')); + if (!sourceMapFile.existsSync()) { + log.warning( + 'Prebuilt SDK source map file "dart_sdk.js.map" ' + 'does not exist at $sdkPath', + ); + return; + } + + await buildStep.writeAsBytes( + jsOutputId.changeExtension(_jsSourceMapExtension), + await sourceMapFile.readAsBytes(), + ); +} diff --git a/build_web_compilers/lib/src/web_entrypoint_builder.dart b/build_web_compilers/lib/src/web_entrypoint_builder.dart index 8452e7590d..30ac3e8d75 100644 --- a/build_web_compilers/lib/src/web_entrypoint_builder.dart +++ b/build_web_compilers/lib/src/web_entrypoint_builder.dart @@ -129,11 +129,24 @@ final class EntrypointBuilderOptions { /// Web hot reload is only supported for DDC's Library Bundle module system. final bool usesWebHotReload; + /// The absolute path to the libraries file for the current platform. + /// + /// If not provided, defaults to "lib/libraries.json" in the sdk directory. + final String? librariesPath; + + /// Whether or not to silence unsupported modules warnings. + /// + /// If `true` then native core library imports that are not officially + /// supported by the current platform will be silently allowed. + final bool silenceUnsupportedModulesWarnings; + EntrypointBuilderOptions({ required this.compilers, this.nativeNullAssertions, this.loaderExtension, this.usesWebHotReload = false, + this.librariesPath, + this.silenceUnsupportedModulesWarnings = false, }); factory EntrypointBuilderOptions.fromOptions(BuilderOptions options) { @@ -146,6 +159,9 @@ final class EntrypointBuilderOptions { const nativeNullAssertionsOption = 'native_null_assertions'; const loaderOption = 'loader'; const webHotReloadOption = 'web-hot-reload'; + const librariesPathOption = 'libraries_path'; + const silenceUnsupportedModulesWarningsOption = + 'silence_unsupported_modules_warnings'; String? defaultLoaderOption; const supportedOptions = [ @@ -156,12 +172,17 @@ final class EntrypointBuilderOptions { dart2wasmArgsOption, loaderOption, webHotReloadOption, + librariesPathOption, + silenceUnsupportedModulesWarningsOption, ]; final config = options.config; final nativeNullAssertions = options.config[nativeNullAssertionsOption] as bool?; final usesWebHotReload = options.config[webHotReloadOption] as bool?; + final librariesPath = options.config[librariesPathOption] as String?; + final silenceUnsupportedModulesWarnings = + options.config[silenceUnsupportedModulesWarningsOption] as bool?; final compilers = []; validateOptions( @@ -249,6 +270,9 @@ final class EntrypointBuilderOptions { ? config[loaderOption] as String? : defaultLoaderOption, usesWebHotReload: usesWebHotReload ?? false, + librariesPath: librariesPath, + silenceUnsupportedModulesWarnings: + silenceUnsupportedModulesWarnings ?? false, ); } @@ -338,6 +362,8 @@ class WebEntrypointBuilder implements Builder { ? _ddcLibraryBundleSdkResources : _ddcSdkResources, usesWebHotReload: usesWebHotReload, + silenceUnsupportedModulesWarnings: + options.silenceUnsupportedModulesWarnings, ); } on MissingModulesException catch (e) { log.severe('$e'); @@ -352,6 +378,9 @@ class WebEntrypointBuilder implements Builder { nativeNullAssertions: options.nativeNullAssertions, onlyCompiler: options.compilers.length == 1, entrypointExtension: compiler.extension, + librariesPath: options.librariesPath, + silenceUnsupportedModulesWarnings: + options.silenceUnsupportedModulesWarnings, ), ); case WebCompiler.Dart2Wasm: @@ -361,6 +390,8 @@ class WebEntrypointBuilder implements Builder { buildStep, compiler.compilerArguments, compiler.extension, + silenceUnsupportedModulesWarnings: + options.silenceUnsupportedModulesWarnings, ); }), ); From 3298e24430c01dcd9834a694f1a21ae5e268d2c6 Mon Sep 17 00:00:00 2001 From: Kilian Schulte Date: Fri, 5 Dec 2025 09:34:35 +0100 Subject: [PATCH 2/8] make additional platform libraries a bool flag --- build_web_compilers/lib/builders.dart | 27 +++++++++------------- build_web_compilers/lib/src/platforms.dart | 11 +++++---- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/build_web_compilers/lib/builders.dart b/build_web_compilers/lib/builders.dart index 3122614d1c..378f0d2518 100644 --- a/build_web_compilers/lib/builders.dart +++ b/build_web_compilers/lib/builders.dart @@ -201,16 +201,13 @@ void _ensureSameDdcHotReloadOptions(BuilderOptions options) { } void _ensureSamePlatformOptions(BuilderOptions options) { - final additionalCoreLibraries = _readAdditionalCoreLibrariesOption(options); - if (_lastAdditionalCoreLibraries == null) { - initializePlatforms(additionalCoreLibraries); - _lastAdditionalCoreLibraries = additionalCoreLibraries; - } else if (!const ListEquality().equals( - _lastAdditionalCoreLibraries, - additionalCoreLibraries, - )) { + final useUiLibraries = _readUseUiLibrariesOption(options); + if (_lastUseUiLibrariesValue == null) { + initializePlatforms(useUiLibraries); + _lastUseUiLibrariesValue = useUiLibraries; + } else if (_lastUseUiLibrariesValue != useUiLibraries) { throw ArgumentError( - '`additional-core-libraries` must be configured the same across the ' + '`use-ui-libraries` must be configured the same across the ' 'following builders: build_web_compilers:ddc, ' 'build_web_compilers|entrypoint, ' 'build_web_compilers|entrypoint_marker, ' @@ -247,10 +244,8 @@ bool _readWebHotReloadOption(BuilderOptions options) { return options.config[_webHotReloadOption] as bool? ?? false; } -List _readAdditionalCoreLibrariesOption(BuilderOptions options) { - return (options.config[_additionalCoreLibrariesOption] as List?) - ?.cast() ?? - []; +bool _readUseUiLibrariesOption(BuilderOptions options) { + return options.config[_useUiLibrariesOption] as bool? ?? false; } String _readDdcKernelPathOption(BuilderOptions options) { @@ -276,7 +271,7 @@ Map _readEnvironmentOption(BuilderOptions options) { Map? _previousDdcConfig; bool? _lastWebHotReloadValue; -List? _lastAdditionalCoreLibraries; +bool? _lastUseUiLibrariesValue; const _useIncrementalCompilerOption = 'use-incremental-compiler'; const _generateFullDillOption = 'generate-full-dill'; const _emitDebugSymbolsOption = 'emit-debug-symbols'; @@ -284,7 +279,7 @@ const _canaryOption = 'canary'; const _trackUnusedInputsCompilerOption = 'track-unused-inputs'; const _environmentOption = 'environment'; const _webHotReloadOption = 'web-hot-reload'; -const _additionalCoreLibrariesOption = 'additional-core-libraries'; +const _useUiLibrariesOption = 'use-ui-libraries'; const _ddcKernelPathOption = 'ddc-kernel-path'; const _librariesPathOption = 'libraries-path'; const _platformSdkOption = 'platform-sdk'; @@ -298,7 +293,7 @@ const _supportedOptions = [ _canaryOption, _trackUnusedInputsCompilerOption, _webHotReloadOption, - _additionalCoreLibrariesOption, + _useUiLibrariesOption, _ddcKernelPathOption, _librariesPathOption, _platformSdkOption, diff --git a/build_web_compilers/lib/src/platforms.dart b/build_web_compilers/lib/src/platforms.dart index d6b9959d89..0eecf3c33d 100644 --- a/build_web_compilers/lib/src/platforms.dart +++ b/build_web_compilers/lib/src/platforms.dart @@ -36,6 +36,9 @@ const _additionalWebLibraries = [ /// Additional libraries supported by dart2wasm. const _additionalWasmLibraries = ['ffi']; +/// Additional libraries supported by the Flutter SDK. +const _additionalUiLibraries = ['ui', 'ui_web']; + // These intentionally throw if [initializePlatforms] wasn't called first. final ddcPlatform = DartPlatform.byName('ddc'); final dart2jsPlatform = DartPlatform.byName('dart2js'); @@ -45,20 +48,20 @@ final dart2wasmPlatform = DartPlatform.byName('dart2wasm'); /// /// Must be called before [ddcPlatform], [dart2jsPlatform], or /// [dart2wasmPlatform] is used. -void initializePlatforms([List additionalCoreLibraries = const []]) { +void initializePlatforms([bool useAdditionalUiLibraries = false]) { DartPlatform.register('ddc', [ ..._coreLibraries, ..._additionalWebLibraries, - ...additionalCoreLibraries, + if (useAdditionalUiLibraries) ..._additionalUiLibraries, ]); DartPlatform.register('dart2js', [ ..._coreLibraries, ..._additionalWebLibraries, - ...additionalCoreLibraries, + if (useAdditionalUiLibraries) ..._additionalUiLibraries, ]); DartPlatform.register('dart2wasm', [ ..._coreLibraries, ..._additionalWasmLibraries, - ...additionalCoreLibraries, + if (useAdditionalUiLibraries) ..._additionalUiLibraries, ]); } From 84985affa81a00d82b99ebcc530399d88ce06d15 Mon Sep 17 00:00:00 2001 From: Kilian Schulte Date: Fri, 5 Dec 2025 11:23:18 +0100 Subject: [PATCH 3/8] fix option usage --- build_web_compilers/lib/builders.dart | 1 + build_web_compilers/lib/src/web_entrypoint_builder.dart | 1 + 2 files changed, 2 insertions(+) diff --git a/build_web_compilers/lib/builders.dart b/build_web_compilers/lib/builders.dart index 378f0d2518..7b11d4e60d 100644 --- a/build_web_compilers/lib/builders.dart +++ b/build_web_compilers/lib/builders.dart @@ -211,6 +211,7 @@ void _ensureSamePlatformOptions(BuilderOptions options) { 'following builders: build_web_compilers:ddc, ' 'build_web_compilers|entrypoint, ' 'build_web_compilers|entrypoint_marker, ' + 'build_web_compilers|ddc, ' 'build_web_compilers|ddc_modules, ' 'build_web_compilers|dart2js_modules, ' 'build_web_compilers|dart2wasm_modules.' diff --git a/build_web_compilers/lib/src/web_entrypoint_builder.dart b/build_web_compilers/lib/src/web_entrypoint_builder.dart index 30ac3e8d75..fc9c3bcda8 100644 --- a/build_web_compilers/lib/src/web_entrypoint_builder.dart +++ b/build_web_compilers/lib/src/web_entrypoint_builder.dart @@ -174,6 +174,7 @@ final class EntrypointBuilderOptions { webHotReloadOption, librariesPathOption, silenceUnsupportedModulesWarningsOption, + 'use-ui-libraries', ]; final config = options.config; From eab7ba9439a1c863502d83884f0ce035de11e13f Mon Sep 17 00:00:00 2001 From: Kilian Schulte Date: Fri, 5 Dec 2025 14:23:09 +0100 Subject: [PATCH 4/8] add and fix tests --- .../lib/build_web_compilers.dart | 2 +- build_web_compilers/lib/builders.dart | 1 - build_web_compilers/lib/src/platforms.dart | 12 +++ build_web_compilers/pubspec.yaml | 1 + .../test/dart2js_bootstrap_test.dart | 90 +++++++++++++++++++ .../test/dart2wasm_bootstrap_test.dart | 1 + .../test/dev_compiler_bootstrap_test.dart | 26 ++++++ .../test/dev_compiler_builder_test.dart | 2 + 8 files changed, 133 insertions(+), 2 deletions(-) diff --git a/build_web_compilers/lib/build_web_compilers.dart b/build_web_compilers/lib/build_web_compilers.dart index 8044292333..6614528743 100644 --- a/build_web_compilers/lib/build_web_compilers.dart +++ b/build_web_compilers/lib/build_web_compilers.dart @@ -13,6 +13,6 @@ export 'src/common.dart' symbolsExtension; export 'src/dev_compiler_builder.dart' show DevCompilerBuilder; export 'src/platforms.dart' - show dart2jsPlatform, dart2wasmPlatform, ddcPlatform; + show dart2jsPlatform, dart2wasmPlatform, ddcPlatform, initializePlatforms; export 'src/web_entrypoint_builder.dart' show WebCompiler, WebEntrypointBuilder, ddcBootstrapExtension; diff --git a/build_web_compilers/lib/builders.dart b/build_web_compilers/lib/builders.dart index 7b11d4e60d..0a369fbc64 100644 --- a/build_web_compilers/lib/builders.dart +++ b/build_web_compilers/lib/builders.dart @@ -9,7 +9,6 @@ import 'package:collection/collection.dart'; import 'build_web_compilers.dart'; import 'src/common.dart'; import 'src/ddc_frontend_server_builder.dart'; -import 'src/platforms.dart'; import 'src/sdk_js_compile_builder.dart'; import 'src/sdk_js_copy_builder.dart'; import 'src/web_entrypoint_marker_builder.dart'; diff --git a/build_web_compilers/lib/src/platforms.dart b/build_web_compilers/lib/src/platforms.dart index 0eecf3c33d..0fc3eb9228 100644 --- a/build_web_compilers/lib/src/platforms.dart +++ b/build_web_compilers/lib/src/platforms.dart @@ -44,11 +44,23 @@ final ddcPlatform = DartPlatform.byName('ddc'); final dart2jsPlatform = DartPlatform.byName('dart2js'); final dart2wasmPlatform = DartPlatform.byName('dart2wasm'); +bool? _useAdditionalUiLibraries; + /// Registers the platforms with [DartPlatform]. /// /// Must be called before [ddcPlatform], [dart2jsPlatform], or /// [dart2wasmPlatform] is used. void initializePlatforms([bool useAdditionalUiLibraries = false]) { + if (_useAdditionalUiLibraries != null) { + if (_useAdditionalUiLibraries != useAdditionalUiLibraries) { + throw ArgumentError( + 'Function initializePlatforms() called multiple times with different ' + 'values. Make sure to call it always with the same value.', + ); + } + return; + } + _useAdditionalUiLibraries = useAdditionalUiLibraries; DartPlatform.register('ddc', [ ..._coreLibraries, ..._additionalWebLibraries, diff --git a/build_web_compilers/pubspec.yaml b/build_web_compilers/pubspec.yaml index cc952ef333..d642bd1b8b 100644 --- a/build_web_compilers/pubspec.yaml +++ b/build_web_compilers/pubspec.yaml @@ -35,6 +35,7 @@ dev_dependencies: d: path: test/fixtures/d dart_flutter_team_lints: ^3.1.0 + file: ^7.0.1 test: ^1.16.0 yaml: ^3.1.0 diff --git a/build_web_compilers/test/dart2js_bootstrap_test.dart b/build_web_compilers/test/dart2js_bootstrap_test.dart index 990cc1a9c5..fb96f8f4d2 100644 --- a/build_web_compilers/test/dart2js_bootstrap_test.dart +++ b/build_web_compilers/test/dart2js_bootstrap_test.dart @@ -12,6 +12,7 @@ import 'package:logging/logging.dart'; import 'package:test/test.dart'; void main() { + initializePlatforms(); final platform = dart2jsPlatform; late StreamSubscription logSubscription; @@ -142,4 +143,93 @@ void main() { outputs: expectedOutputs, ); }); + + test('throws on unsupported platform library imports', () async { + final assets = { + 'a|lib/index.dart': ''' + import 'dart:io'; + main() { + print('hello world'); + } + ''', + }; + final expectedOutputs = { + 'a|lib/.dart2js.meta_module.clean': isNotNull, + 'a|lib/.dart2js.meta_module.raw': isNotNull, + 'a|lib/index.dart2js.module': isNotNull, + 'a|lib/index.module.library': isNotNull, + }; + final logs = []; + await testBuilders( + [ + const ModuleLibraryBuilder(), + MetaModuleBuilder(platform), + MetaModuleCleanBuilder(platform), + ModuleBuilder(platform), + WebEntrypointBuilder.fromOptions( + const BuilderOptions({ + 'compiler': 'dart2js', + 'native_null_assertions': false, + }), + ), + ], + assets, + outputs: expectedOutputs, + onLog: logs.add, + ); + expect( + logs, + contains( + isA().having( + (r) => r.message, + 'message', + contains( + 'Skipping compiling a|lib/index.dart with dart2js because some of ' + 'its\ntransitive libraries have sdk dependencies that are not ' + 'supported on this platform:\n\na|lib/index.dart', + ), + ), + ), + ); + }); + + test( + 'ignores unsupported platform library imports when silence flag is set', + () async { + final assets = { + 'a|lib/index.dart': ''' + import 'dart:io'; + main() { + print('hello world'); + } + ''', + }; + final expectedOutputs = { + 'a|lib/.dart2js.meta_module.clean': isNotNull, + 'a|lib/.dart2js.meta_module.raw': isNotNull, + 'a|lib/index.dart.js.map': isNotNull, + 'a|lib/index.dart.js.tar.gz': isNotNull, + 'a|lib/index.dart.js': decodedMatches(contains('world')), + 'a|lib/index.dart2js.module': isNotNull, + 'a|lib/index.module.library': isNotNull, + }; + await testBuilders( + [ + const ModuleLibraryBuilder(), + MetaModuleBuilder(platform), + MetaModuleCleanBuilder(platform), + ModuleBuilder(platform), + WebEntrypointBuilder.fromOptions( + const BuilderOptions({ + 'compiler': 'dart2js', + 'native_null_assertions': false, + 'silence_unsupported_modules_warnings': true, + }), + ), + ], + assets, + outputs: expectedOutputs, + ); + }, + ); } diff --git a/build_web_compilers/test/dart2wasm_bootstrap_test.dart b/build_web_compilers/test/dart2wasm_bootstrap_test.dart index c6adbb5193..1c1877d7ad 100644 --- a/build_web_compilers/test/dart2wasm_bootstrap_test.dart +++ b/build_web_compilers/test/dart2wasm_bootstrap_test.dart @@ -9,6 +9,7 @@ import 'package:build_web_compilers/build_web_compilers.dart'; import 'package:test/test.dart'; void main() { + initializePlatforms(); final startingAssets = { 'a|web/index.dart': ''' void main() { diff --git a/build_web_compilers/test/dev_compiler_bootstrap_test.dart b/build_web_compilers/test/dev_compiler_bootstrap_test.dart index 0bda980b02..7891275d1b 100644 --- a/build_web_compilers/test/dev_compiler_bootstrap_test.dart +++ b/build_web_compilers/test/dev_compiler_bootstrap_test.dart @@ -2,14 +2,18 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'dart:io'; + import 'package:build/build.dart'; import 'package:build_modules/build_modules.dart'; import 'package:build_test/build_test.dart'; import 'package:build_web_compilers/build_web_compilers.dart'; import 'package:build_web_compilers/builders.dart'; +import 'package:file/memory.dart'; import 'package:test/test.dart'; void main() { + initializePlatforms(); final startingBuilders = { // Uses the real sdk copy builder to copy required files from the SDK. sdkJsCopyRequirejs(const BuilderOptions({})), @@ -253,5 +257,27 @@ void main() { }; await testBuilder(builder, sdkAssets, outputs: expectedOutputs); }); + + test('can use prebuilt sdk from path', () async { + final builder = sdkJsCompile( + const BuilderOptions({'use-prebuilt-sdk-from-path': 'path/to/sdk'}), + ); + final sdkAssets = {'build_web_compilers|fake.txt': ''}; + final expectedOutputs = { + 'build_web_compilers|lib/src/dev_compiler/dart_sdk.js': decodedMatches( + 'prebuilt-sdk', + ), + 'build_web_compilers|lib/src/dev_compiler/dart_sdk.js.map': + decodedMatches('prebuilt-sdk-map'), + }; + final fs = MemoryFileSystem(); + fs.directory('path/to/sdk') + ..createSync(recursive: true) + ..childFile('dart_sdk.js').writeAsStringSync('prebuilt-sdk') + ..childFile('dart_sdk.js.map').writeAsStringSync('prebuilt-sdk-map'); + await IOOverrides.runZoned(createFile: fs.file, () async { + await testBuilder(builder, sdkAssets, outputs: expectedOutputs); + }); + }); }); } diff --git a/build_web_compilers/test/dev_compiler_builder_test.dart b/build_web_compilers/test/dev_compiler_builder_test.dart index e3e7f6fe14..235bdd3b7e 100644 --- a/build_web_compilers/test/dev_compiler_builder_test.dart +++ b/build_web_compilers/test/dev_compiler_builder_test.dart @@ -11,6 +11,8 @@ import 'package:logging/logging.dart'; import 'package:test/test.dart'; void main() { + initializePlatforms(); + group('error free project', () { final startingAssets = { 'a|lib/a.dart': r''' From fcd972870370187ab393981e7aeed02d0c124236 Mon Sep 17 00:00:00 2001 From: Kilian Schulte Date: Sat, 6 Dec 2025 00:16:04 +0100 Subject: [PATCH 5/8] change naming of unsafe compile option --- .../lib/src/dart2js_bootstrap.dart | 8 ++--- .../lib/src/dart2wasm_bootstrap.dart | 8 ++--- .../lib/src/dev_compiler_bootstrap.dart | 4 +-- .../lib/src/web_entrypoint_builder.dart | 31 +++++++++---------- .../test/dart2js_bootstrap_test.dart | 4 +-- 5 files changed, 27 insertions(+), 28 deletions(-) diff --git a/build_web_compilers/lib/src/dart2js_bootstrap.dart b/build_web_compilers/lib/src/dart2js_bootstrap.dart index 70a0a00c6d..d37ec2f99a 100644 --- a/build_web_compilers/lib/src/dart2js_bootstrap.dart +++ b/build_web_compilers/lib/src/dart2js_bootstrap.dart @@ -29,7 +29,7 @@ Future bootstrapDart2Js( required bool onlyCompiler, String entrypointExtension = jsEntrypointExtension, String? librariesPath, - bool silenceUnsupportedModulesWarnings = false, + bool unsafeAllowUnsupportedModules = false, }) => _resourcePool.withResource( () => _bootstrapDart2Js( buildStep, @@ -38,7 +38,7 @@ Future bootstrapDart2Js( onlyCompiler: onlyCompiler, entrypointExtension: entrypointExtension, librariesPath: librariesPath, - silenceUnsupportedModulesWarnings: silenceUnsupportedModulesWarnings, + unsafeAllowUnsupportedModules: unsafeAllowUnsupportedModules, ), ); @@ -49,7 +49,7 @@ Future _bootstrapDart2Js( required bool onlyCompiler, required String entrypointExtension, String? librariesPath, - bool silenceUnsupportedModulesWarnings = false, + bool unsafeAllowUnsupportedModules = false, }) async { final dartEntrypointId = buildStep.inputId; final moduleId = dartEntrypointId.changeExtension( @@ -65,7 +65,7 @@ Future _bootstrapDart2Js( try { allDeps = (await module.computeTransitiveDependencies( buildStep, - throwIfUnsupported: !silenceUnsupportedModulesWarnings, + throwIfUnsupported: !unsafeAllowUnsupportedModules, ))..add(module); } on UnsupportedModules catch (e) { final librariesString = (await e.exactLibraries(buildStep).toList()) diff --git a/build_web_compilers/lib/src/dart2wasm_bootstrap.dart b/build_web_compilers/lib/src/dart2wasm_bootstrap.dart index be28f8620d..ffdd20a859 100644 --- a/build_web_compilers/lib/src/dart2wasm_bootstrap.dart +++ b/build_web_compilers/lib/src/dart2wasm_bootstrap.dart @@ -46,14 +46,14 @@ Future bootstrapDart2Wasm( BuildStep buildStep, List additionalArguments, String javaScriptModuleExtension, { - bool silenceUnsupportedModulesWarnings = false, + bool unsafeAllowUnsupportedModules = false, }) async { return await _resourcePool.withResource( () => _bootstrapDart2Wasm( buildStep, additionalArguments, javaScriptModuleExtension, - silenceUnsupportedModulesWarnings: silenceUnsupportedModulesWarnings, + unsafeAllowUnsupportedModules: unsafeAllowUnsupportedModules, ), ); } @@ -62,7 +62,7 @@ Future _bootstrapDart2Wasm( BuildStep buildStep, List additionalArguments, String javaScriptModuleExtension, { - bool silenceUnsupportedModulesWarnings = false, + bool unsafeAllowUnsupportedModules = false, }) async { final dartEntrypointId = buildStep.inputId; final moduleId = dartEntrypointId.changeExtension( @@ -78,7 +78,7 @@ Future _bootstrapDart2Wasm( try { allDeps = (await module.computeTransitiveDependencies( buildStep, - throwIfUnsupported: !silenceUnsupportedModulesWarnings, + throwIfUnsupported: !unsafeAllowUnsupportedModules, ))..add(module); } on UnsupportedModules catch (e) { final librariesString = (await e.exactLibraries(buildStep).toList()) diff --git a/build_web_compilers/lib/src/dev_compiler_bootstrap.dart b/build_web_compilers/lib/src/dev_compiler_bootstrap.dart index eb3ccefa22..6d5af8a8bf 100644 --- a/build_web_compilers/lib/src/dev_compiler_bootstrap.dart +++ b/build_web_compilers/lib/src/dev_compiler_bootstrap.dart @@ -37,7 +37,7 @@ Future bootstrapDdc( String entrypointExtension = jsEntrypointExtension, required bool? nativeNullAssertions, bool usesWebHotReload = false, - bool silenceUnsupportedModulesWarnings = false, + bool unsafeAllowUnsupportedModules = false, }) async { // Ensures that the sdk resources are built and available. await _ensureResources(buildStep, requiredAssets); @@ -57,7 +57,7 @@ Future bootstrapDdc( module, buildStep, computeStronglyConnectedComponents: !usesWebHotReload, - throwIfUnsupported: !silenceUnsupportedModulesWarnings, + throwIfUnsupported: !unsafeAllowUnsupportedModules, ); } on UnsupportedModules catch (e) { final librariesString = (await e.exactLibraries(buildStep).toList()) diff --git a/build_web_compilers/lib/src/web_entrypoint_builder.dart b/build_web_compilers/lib/src/web_entrypoint_builder.dart index fc9c3bcda8..959d2cb801 100644 --- a/build_web_compilers/lib/src/web_entrypoint_builder.dart +++ b/build_web_compilers/lib/src/web_entrypoint_builder.dart @@ -134,11 +134,11 @@ final class EntrypointBuilderOptions { /// If not provided, defaults to "lib/libraries.json" in the sdk directory. final String? librariesPath; - /// Whether or not to silence unsupported modules warnings. + /// Whether or not to allow unsupported modules. /// /// If `true` then native core library imports that are not officially /// supported by the current platform will be silently allowed. - final bool silenceUnsupportedModulesWarnings; + final bool unsafeAllowUnsupportedModules; EntrypointBuilderOptions({ required this.compilers, @@ -146,7 +146,7 @@ final class EntrypointBuilderOptions { this.loaderExtension, this.usesWebHotReload = false, this.librariesPath, - this.silenceUnsupportedModulesWarnings = false, + this.unsafeAllowUnsupportedModules = false, }); factory EntrypointBuilderOptions.fromOptions(BuilderOptions options) { @@ -160,8 +160,8 @@ final class EntrypointBuilderOptions { const loaderOption = 'loader'; const webHotReloadOption = 'web-hot-reload'; const librariesPathOption = 'libraries_path'; - const silenceUnsupportedModulesWarningsOption = - 'silence_unsupported_modules_warnings'; + const unsafeAllowUnsupportedModulesOption = + 'unsafe_allow_unsupported_modules'; String? defaultLoaderOption; const supportedOptions = [ @@ -173,7 +173,7 @@ final class EntrypointBuilderOptions { loaderOption, webHotReloadOption, librariesPathOption, - silenceUnsupportedModulesWarningsOption, + unsafeAllowUnsupportedModulesOption, 'use-ui-libraries', ]; @@ -182,8 +182,8 @@ final class EntrypointBuilderOptions { options.config[nativeNullAssertionsOption] as bool?; final usesWebHotReload = options.config[webHotReloadOption] as bool?; final librariesPath = options.config[librariesPathOption] as String?; - final silenceUnsupportedModulesWarnings = - options.config[silenceUnsupportedModulesWarningsOption] as bool?; + final unsafeAllowUnsupportedModules = + options.config[unsafeAllowUnsupportedModulesOption] as bool?; final compilers = []; validateOptions( @@ -272,8 +272,7 @@ final class EntrypointBuilderOptions { : defaultLoaderOption, usesWebHotReload: usesWebHotReload ?? false, librariesPath: librariesPath, - silenceUnsupportedModulesWarnings: - silenceUnsupportedModulesWarnings ?? false, + unsafeAllowUnsupportedModules: unsafeAllowUnsupportedModules ?? false, ); } @@ -363,8 +362,8 @@ class WebEntrypointBuilder implements Builder { ? _ddcLibraryBundleSdkResources : _ddcSdkResources, usesWebHotReload: usesWebHotReload, - silenceUnsupportedModulesWarnings: - options.silenceUnsupportedModulesWarnings, + unsafeAllowUnsupportedModules: + options.unsafeAllowUnsupportedModules, ); } on MissingModulesException catch (e) { log.severe('$e'); @@ -380,8 +379,8 @@ class WebEntrypointBuilder implements Builder { onlyCompiler: options.compilers.length == 1, entrypointExtension: compiler.extension, librariesPath: options.librariesPath, - silenceUnsupportedModulesWarnings: - options.silenceUnsupportedModulesWarnings, + unsafeAllowUnsupportedModules: + options.unsafeAllowUnsupportedModules, ), ); case WebCompiler.Dart2Wasm: @@ -391,8 +390,8 @@ class WebEntrypointBuilder implements Builder { buildStep, compiler.compilerArguments, compiler.extension, - silenceUnsupportedModulesWarnings: - options.silenceUnsupportedModulesWarnings, + unsafeAllowUnsupportedModules: + options.unsafeAllowUnsupportedModules, ); }), ); diff --git a/build_web_compilers/test/dart2js_bootstrap_test.dart b/build_web_compilers/test/dart2js_bootstrap_test.dart index fb96f8f4d2..257dec439b 100644 --- a/build_web_compilers/test/dart2js_bootstrap_test.dart +++ b/build_web_compilers/test/dart2js_bootstrap_test.dart @@ -194,7 +194,7 @@ void main() { }); test( - 'ignores unsupported platform library imports when silence flag is set', + 'ignores unsupported platform library imports when allow flag is set', () async { final assets = { 'a|lib/index.dart': ''' @@ -223,7 +223,7 @@ void main() { const BuilderOptions({ 'compiler': 'dart2js', 'native_null_assertions': false, - 'silence_unsupported_modules_warnings': true, + 'unsafe_allow_unsupported_modules': true, }), ), ], From de73a9a445b6acd4b65fe52d0b86c754fcd2d264 Mon Sep 17 00:00:00 2001 From: Kilian Schulte Date: Sat, 6 Dec 2025 00:16:34 +0100 Subject: [PATCH 6/8] Update changelog and version --- build_web_compilers/CHANGELOG.md | 4 ++++ build_web_compilers/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/build_web_compilers/CHANGELOG.md b/build_web_compilers/CHANGELOG.md index dc0def7012..91f27cb8e8 100644 --- a/build_web_compilers/CHANGELOG.md +++ b/build_web_compilers/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.4.6 + +- Add build options to customize the SDK used for compiling to js and wasm. + ## 4.4.5 - Updating DDC's bootstrapper to be consistent with the rest of the ecosystem. diff --git a/build_web_compilers/pubspec.yaml b/build_web_compilers/pubspec.yaml index d642bd1b8b..1a03e75b68 100644 --- a/build_web_compilers/pubspec.yaml +++ b/build_web_compilers/pubspec.yaml @@ -1,5 +1,5 @@ name: build_web_compilers -version: 4.4.5 +version: 4.4.6 description: Builder implementations wrapping the dart2js and DDC compilers. repository: https://github.com/dart-lang/build/tree/master/build_web_compilers resolution: workspace From 5b97d7969449836a6f2e518e8679b9837e7d1d07 Mon Sep 17 00:00:00 2001 From: Kilian Schulte Date: Mon, 8 Dec 2025 10:45:53 +0100 Subject: [PATCH 7/8] document options in readme --- build_web_compilers/README.md | 27 +++++++++++++++++++ .../lib/src/web_entrypoint_builder.dart | 4 +-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/build_web_compilers/README.md b/build_web_compilers/README.md index ab5a7ec3aa..26d11fd17f 100644 --- a/build_web_compilers/README.md +++ b/build_web_compilers/README.md @@ -164,6 +164,33 @@ targets: In this case, you need to use another builder or a predefined loader instead. +### Advanced SDK Customization + +The following options allow you to customize the Dart SDK used for compiling to +js and wasm. They are intended for advanced use cases and should be used with +caution. + +
+Expand to see configuration options. + +```yaml +global_options: + build_web_compilers:ddc: + options: + use-ui-libraries: false + platform-sdk: /path/to/platform_sdk/ + ddc-kernel-path: relative/path/to/kernel_summary + libraries-path: /path/to/libraries.json + build_web_compilers:entrypoint: + options: + use-ui-libraries: false + libraries-path: /path/to/libraries.json + build_web_compilers:sdk_js: + options: + use-prebuilt-sdk-from-path: /path/to/prebuilt/sdk_js/ +``` +
+ ### Configuring -D environment variables dartdevc is a modular compiler, so in order to ensure consistent builds diff --git a/build_web_compilers/lib/src/web_entrypoint_builder.dart b/build_web_compilers/lib/src/web_entrypoint_builder.dart index 959d2cb801..3fd13cf8ad 100644 --- a/build_web_compilers/lib/src/web_entrypoint_builder.dart +++ b/build_web_compilers/lib/src/web_entrypoint_builder.dart @@ -159,9 +159,9 @@ final class EntrypointBuilderOptions { const nativeNullAssertionsOption = 'native_null_assertions'; const loaderOption = 'loader'; const webHotReloadOption = 'web-hot-reload'; - const librariesPathOption = 'libraries_path'; + const librariesPathOption = 'libraries-path'; const unsafeAllowUnsupportedModulesOption = - 'unsafe_allow_unsupported_modules'; + 'unsafe-allow-unsupported-modules'; String? defaultLoaderOption; const supportedOptions = [ From 3297d3a1b4c12cedc35fd77636796e977ff253a2 Mon Sep 17 00:00:00 2001 From: Kilian Schulte Date: Mon, 8 Dec 2025 19:34:39 +0100 Subject: [PATCH 8/8] fix tests --- build_web_compilers/test/dart2js_bootstrap_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_web_compilers/test/dart2js_bootstrap_test.dart b/build_web_compilers/test/dart2js_bootstrap_test.dart index 257dec439b..adc028a1d2 100644 --- a/build_web_compilers/test/dart2js_bootstrap_test.dart +++ b/build_web_compilers/test/dart2js_bootstrap_test.dart @@ -223,7 +223,7 @@ void main() { const BuilderOptions({ 'compiler': 'dart2js', 'native_null_assertions': false, - 'unsafe_allow_unsupported_modules': true, + 'unsafe-allow-unsupported-modules': true, }), ), ],