diff --git a/build_web_compilers/CHANGELOG.md b/build_web_compilers/CHANGELOG.md
index dc0def701..91f27cb8e 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/README.md b/build_web_compilers/README.md
index ab5a7ec3a..26d11fd17 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/build_web_compilers.dart b/build_web_compilers/lib/build_web_compilers.dart
index 804429233..661452874 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 f11ddac3e..0a369fbc6 100644
--- a/build_web_compilers/lib/builders.dart
+++ b/build_web_compilers/lib/builders.dart
@@ -15,11 +15,13 @@ 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 +30,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 +52,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 +66,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 +79,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 +104,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 +199,27 @@ void _ensureSameDdcHotReloadOptions(BuilderOptions options) {
}
}
+void _ensureSamePlatformOptions(BuilderOptions options) {
+ final useUiLibraries = _readUseUiLibrariesOption(options);
+ if (_lastUseUiLibrariesValue == null) {
+ initializePlatforms(useUiLibraries);
+ _lastUseUiLibrariesValue = useUiLibraries;
+ } else if (_lastUseUiLibrariesValue != useUiLibraries) {
+ throw ArgumentError(
+ '`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, '
+ 'build_web_compilers|ddc, '
+ '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 +244,26 @@ bool _readWebHotReloadOption(BuilderOptions options) {
return options.config[_webHotReloadOption] as bool? ?? false;
}
+bool _readUseUiLibrariesOption(BuilderOptions options) {
+ return options.config[_useUiLibrariesOption] as bool? ?? false;
+}
+
+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 +271,7 @@ Map _readEnvironmentOption(BuilderOptions options) {
Map? _previousDdcConfig;
bool? _lastWebHotReloadValue;
+bool? _lastUseUiLibrariesValue;
const _useIncrementalCompilerOption = 'use-incremental-compiler';
const _generateFullDillOption = 'generate-full-dill';
const _emitDebugSymbolsOption = 'emit-debug-symbols';
@@ -208,6 +279,11 @@ const _canaryOption = 'canary';
const _trackUnusedInputsCompilerOption = 'track-unused-inputs';
const _environmentOption = 'environment';
const _webHotReloadOption = 'web-hot-reload';
+const _useUiLibrariesOption = 'use-ui-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 +293,8 @@ const _supportedOptions = [
_canaryOption,
_trackUnusedInputsCompilerOption,
_webHotReloadOption,
+ _useUiLibrariesOption,
+ _ddcKernelPathOption,
+ _librariesPathOption,
+ _platformSdkOption,
];
diff --git a/build_web_compilers/lib/src/dart2js_bootstrap.dart b/build_web_compilers/lib/src/dart2js_bootstrap.dart
index f3c431578..d37ec2f99 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 unsafeAllowUnsupportedModules = false,
}) => _resourcePool.withResource(
() => _bootstrapDart2Js(
buildStep,
@@ -35,6 +37,8 @@ Future bootstrapDart2Js(
nativeNullAssertions: nativeNullAssertions,
onlyCompiler: onlyCompiler,
entrypointExtension: entrypointExtension,
+ librariesPath: librariesPath,
+ unsafeAllowUnsupportedModules: unsafeAllowUnsupportedModules,
),
);
@@ -44,6 +48,8 @@ Future _bootstrapDart2Js(
required bool? nativeNullAssertions,
required bool onlyCompiler,
required String entrypointExtension,
+ String? librariesPath,
+ bool unsafeAllowUnsupportedModules = 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: !unsafeAllowUnsupportedModules,
))..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 690e0f769..ffdd20a85 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 unsafeAllowUnsupportedModules = false,
+}) async {
return await _resourcePool.withResource(
() => _bootstrapDart2Wasm(
buildStep,
additionalArguments,
javaScriptModuleExtension,
+ unsafeAllowUnsupportedModules: unsafeAllowUnsupportedModules,
),
);
}
@@ -59,8 +61,9 @@ Future bootstrapDart2Wasm(
Future _bootstrapDart2Wasm(
BuildStep buildStep,
List additionalArguments,
- String javaScriptModuleExtension,
-) async {
+ String javaScriptModuleExtension, {
+ bool unsafeAllowUnsupportedModules = 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: !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 bb71c44f9..6d5af8a8b 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 unsafeAllowUnsupportedModules = 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: !unsafeAllowUnsupportedModules,
);
} 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 e99446e52..0fc3eb922 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,44 @@ const _additionalWebLibraries = [
/// Additional libraries supported by dart2wasm.
const _additionalWasmLibraries = ['ffi'];
-const _jsCompilerLibraries = [..._coreLibraries, ..._additionalWebLibraries];
+/// Additional libraries supported by the Flutter SDK.
+const _additionalUiLibraries = ['ui', 'ui_web'];
-final ddcPlatform = DartPlatform.register('ddc', _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 dart2jsPlatform = DartPlatform.register('dart2js', _jsCompilerLibraries);
+bool? _useAdditionalUiLibraries;
-final dart2wasmPlatform = DartPlatform.register('dart2wasm', [
- ..._coreLibraries,
- ..._additionalWasmLibraries,
-]);
+/// 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,
+ if (useAdditionalUiLibraries) ..._additionalUiLibraries,
+ ]);
+ DartPlatform.register('dart2js', [
+ ..._coreLibraries,
+ ..._additionalWebLibraries,
+ if (useAdditionalUiLibraries) ..._additionalUiLibraries,
+ ]);
+ DartPlatform.register('dart2wasm', [
+ ..._coreLibraries,
+ ..._additionalWasmLibraries,
+ if (useAdditionalUiLibraries) ..._additionalUiLibraries,
+ ]);
+}
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 824fc8983..fe2b9e037 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 8452e7590..3fd13cf8a 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 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 unsafeAllowUnsupportedModules;
+
EntrypointBuilderOptions({
required this.compilers,
this.nativeNullAssertions,
this.loaderExtension,
this.usesWebHotReload = false,
+ this.librariesPath,
+ this.unsafeAllowUnsupportedModules = 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 unsafeAllowUnsupportedModulesOption =
+ 'unsafe-allow-unsupported-modules';
String? defaultLoaderOption;
const supportedOptions = [
@@ -156,12 +172,18 @@ final class EntrypointBuilderOptions {
dart2wasmArgsOption,
loaderOption,
webHotReloadOption,
+ librariesPathOption,
+ unsafeAllowUnsupportedModulesOption,
+ 'use-ui-libraries',
];
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 unsafeAllowUnsupportedModules =
+ options.config[unsafeAllowUnsupportedModulesOption] as bool?;
final compilers = [];
validateOptions(
@@ -249,6 +271,8 @@ final class EntrypointBuilderOptions {
? config[loaderOption] as String?
: defaultLoaderOption,
usesWebHotReload: usesWebHotReload ?? false,
+ librariesPath: librariesPath,
+ unsafeAllowUnsupportedModules: unsafeAllowUnsupportedModules ?? false,
);
}
@@ -338,6 +362,8 @@ class WebEntrypointBuilder implements Builder {
? _ddcLibraryBundleSdkResources
: _ddcSdkResources,
usesWebHotReload: usesWebHotReload,
+ unsafeAllowUnsupportedModules:
+ options.unsafeAllowUnsupportedModules,
);
} 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,
+ unsafeAllowUnsupportedModules:
+ options.unsafeAllowUnsupportedModules,
),
);
case WebCompiler.Dart2Wasm:
@@ -361,6 +390,8 @@ class WebEntrypointBuilder implements Builder {
buildStep,
compiler.compilerArguments,
compiler.extension,
+ unsafeAllowUnsupportedModules:
+ options.unsafeAllowUnsupportedModules,
);
}),
);
diff --git a/build_web_compilers/pubspec.yaml b/build_web_compilers/pubspec.yaml
index cc952ef33..1a03e75b6 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
@@ -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 990cc1a9c..adc028a1d 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 allow 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,
+ 'unsafe-allow-unsupported-modules': 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 c6adbb519..1c1877d7a 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 0bda980b0..7891275d1 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 e3e7f6fe1..235bdd3b7 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'''