From 52a7e60d3caafbc7175a88ba4f8ed52a71651d9f Mon Sep 17 00:00:00 2001 From: Nate Biggs Date: Fri, 2 Oct 2026 23:32:24 -0400 Subject: [PATCH 1/6] [dwds] Add support for --[no-]deprecated-js-interop The Dart SDK added a `--[no-]deprecated-js-interop` flag to its web compilers (https://dart-review.googlesource.com/c/sdk/+/555460, https://dart-review.googlesource.com/c/sdk/+/555500). With `--no-deprecated-js-interop`, the compilers reject imports of `dart:html`, `dart:js`, `dart:js_util`, `package:js` and the other deprecated JS interop libraries. This plumbs the flag into DWDS's expression evaluation: - **New field:** `BuildSettings` and `CompilerOptions` take an optional `bool? deprecatedJsInterop`. This is a non-breaking addition. - **Expression compiler worker:** started with `--[no-]deprecated-js-interop` only when the setting is non-null. - **Testable arguments:** the worker arguments are now built by a separate function, `expressionCompilerWorkerArgs`, so they can be unit-tested. --- dwds/CHANGELOG.md | 7 +++ dwds/lib/src/loaders/strategy.dart | 7 +++ .../services/chrome/chrome_proxy_service.dart | 8 +-- .../lib/src/services/expression_compiler.dart | 7 +++ .../services/expression_compiler_service.dart | 57 ++++++++++++++----- dwds/lib/src/version.dart | 2 +- dwds/pubspec.yaml | 2 +- .../expression_compiler_worker_args_test.dart | 57 +++++++++++++++++++ 8 files changed, 126 insertions(+), 21 deletions(-) create mode 100644 dwds/test/services/expression_compiler_worker_args_test.dart diff --git a/dwds/CHANGELOG.md b/dwds/CHANGELOG.md index a67023add2..3902973170 100644 --- a/dwds/CHANGELOG.md +++ b/dwds/CHANGELOG.md @@ -1,3 +1,10 @@ +## 27.2.0-wip + +- Add `deprecatedJsInterop` to `BuildSettings` and `CompilerOptions`. When it + is set, the expression compiler worker is started with + `--[no-]deprecated-js-interop`. This requires a Dart SDK that supports the + flag. + ## 27.1.4 - Fix duplicated browser tabs taking over the original tab's DWDS connection. diff --git a/dwds/lib/src/loaders/strategy.dart b/dwds/lib/src/loaders/strategy.dart index c4ccaa6aa9..eea2416231 100644 --- a/dwds/lib/src/loaders/strategy.dart +++ b/dwds/lib/src/loaders/strategy.dart @@ -236,10 +236,17 @@ class BuildSettings { final bool isFlutterApp; final List experiments; + /// Whether the compilers allow the deprecated JS interop libraries, such as + /// `dart:html`. + /// + /// If `null`, no flag is passed and the compiler default is used. + final bool? deprecatedJsInterop; + const BuildSettings({ this.appEntrypoint, this.canaryFeatures = false, this.isFlutterApp = true, this.experiments = const [], + this.deprecatedJsInterop, }); } diff --git a/dwds/lib/src/services/chrome/chrome_proxy_service.dart b/dwds/lib/src/services/chrome/chrome_proxy_service.dart index 1add07eece..ad785f3b01 100644 --- a/dwds/lib/src/services/chrome/chrome_proxy_service.dart +++ b/dwds/lib/src/services/chrome/chrome_proxy_service.dart @@ -186,15 +186,15 @@ final class ChromeProxyService extends ProxyService { Future _updateCompilerDependencies(String entrypoint) async { final loadStrategy = globalToolConfiguration.loadStrategy; final moduleFormat = loadStrategy.moduleFormat; - final canaryFeatures = loadStrategy.buildSettings.canaryFeatures; - final experiments = loadStrategy.buildSettings.experiments; + final buildSettings = loadStrategy.buildSettings; _logger.info('Initializing expression compiler for $entrypoint'); final compilerOptions = CompilerOptions( moduleFormat: ModuleFormat.values.byName(moduleFormat), - canaryFeatures: canaryFeatures, - experiments: experiments, + canaryFeatures: buildSettings.canaryFeatures, + experiments: buildSettings.experiments, + deprecatedJsInterop: buildSettings.deprecatedJsInterop, ); final compiler = _compiler; diff --git a/dwds/lib/src/services/expression_compiler.dart b/dwds/lib/src/services/expression_compiler.dart index 2d7803a413..15e143368a 100644 --- a/dwds/lib/src/services/expression_compiler.dart +++ b/dwds/lib/src/services/expression_compiler.dart @@ -9,10 +9,17 @@ class CompilerOptions { final bool canaryFeatures; final List experiments; + /// Whether the compiler allows the deprecated JS interop libraries, such as + /// `dart:html`. + /// + /// If `null`, no flag is passed and the compiler default is used. + final bool? deprecatedJsInterop; + CompilerOptions({ required this.moduleFormat, required this.canaryFeatures, required this.experiments, + this.deprecatedJsInterop, }); } diff --git a/dwds/lib/src/services/expression_compiler_service.dart b/dwds/lib/src/services/expression_compiler_service.dart index 4e7740de5a..cf5cc12726 100644 --- a/dwds/lib/src/services/expression_compiler_service.dart +++ b/dwds/lib/src/services/expression_compiler_service.dart @@ -9,6 +9,41 @@ import 'package:async/async.dart'; import 'package:dwds/src/services/expression_compiler.dart'; import 'package:dwds/src/utilities/sdk_configuration.dart'; import 'package:logging/logging.dart'; +import 'package:meta/meta.dart'; + +/// Returns the arguments for the DDC expression compiler worker. +@visibleForTesting +List expressionCompilerWorkerArgs({ + required Uri sdkSummaryUri, + required String address, + required int port, + required CompilerOptions compilerOptions, + required bool verbose, +}) => [ + '--experimental-expression-compiler', + '--dart-sdk-summary', + '$sdkSummaryUri', + '--asset-server-address', + address, + '--asset-server-port', + '$port', + '--module-format', + compilerOptions.moduleFormat.name, + if (verbose) '--verbose', + for (final experiment in compilerOptions.experiments) + '--enable-experiment=$experiment', + if (compilerOptions.canaryFeatures) '--canary', + ?_deprecatedJsInteropArg(compilerOptions.deprecatedJsInterop), +]; + +/// The `--[no-]deprecated-js-interop` argument, or `null` to use the compiler +/// default. +String? _deprecatedJsInteropArg(bool? deprecatedJsInterop) => + switch (deprecatedJsInterop) { + null => null, + true => '--deprecated-js-interop', + false => '--no-deprecated-js-interop', + }; class _Compiler { static final _logger = Logger('ExpressionCompilerService'); @@ -67,21 +102,13 @@ class _Compiler { final workerUri = sdkConfiguration.compilerWorkerUri!; final sdkSummaryUri = sdkConfiguration.sdkSummaryUri!; - final args = [ - '--experimental-expression-compiler', - '--dart-sdk-summary', - '$sdkSummaryUri', - '--asset-server-address', - address, - '--asset-server-port', - '$port', - '--module-format', - compilerOptions.moduleFormat.name, - if (verbose) '--verbose', - for (final experiment in compilerOptions.experiments) - '--enable-experiment=$experiment', - if (compilerOptions.canaryFeatures) '--canary', - ]; + final args = expressionCompilerWorkerArgs( + sdkSummaryUri: sdkSummaryUri, + address: address, + port: port, + compilerOptions: compilerOptions, + verbose: verbose, + ); _logger.info('Starting...'); _logger.finest('$workerUri ${args.join(' ')}'); diff --git a/dwds/lib/src/version.dart b/dwds/lib/src/version.dart index e7267f63a2..aeec9f16b7 100644 --- a/dwds/lib/src/version.dart +++ b/dwds/lib/src/version.dart @@ -1,2 +1,2 @@ // Generated code. Do not modify. -const packageVersion = '27.1.4'; +const packageVersion = '27.2.0-wip'; diff --git a/dwds/pubspec.yaml b/dwds/pubspec.yaml index 42421f8b78..1cebe5fc3e 100644 --- a/dwds/pubspec.yaml +++ b/dwds/pubspec.yaml @@ -1,6 +1,6 @@ name: dwds # Every time this changes you need to run `dart run tool/build.dart`. -version: 27.1.4 +version: 27.2.0-wip description: >- A service that proxies between the Chrome debug protocol and the Dart VM diff --git a/dwds/test/services/expression_compiler_worker_args_test.dart b/dwds/test/services/expression_compiler_worker_args_test.dart new file mode 100644 index 0000000000..79ff56595a --- /dev/null +++ b/dwds/test/services/expression_compiler_worker_args_test.dart @@ -0,0 +1,57 @@ +// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file +// 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 'package:dwds/src/services/expression_compiler.dart'; +import 'package:dwds/src/services/expression_compiler_service.dart'; +import 'package:test/test.dart'; + +void main() { + group('expressionCompilerWorkerArgs', () { + List argsFor({bool? deprecatedJsInterop}) => + expressionCompilerWorkerArgs( + sdkSummaryUri: Uri.file('/sdk/ddc_outline.dill'), + address: 'localhost', + port: 1234, + compilerOptions: CompilerOptions( + moduleFormat: ModuleFormat.ddc, + canaryFeatures: true, + experiments: const ['records'], + deprecatedJsInterop: deprecatedJsInterop, + ), + verbose: false, + ); + + test('passes the compiler options', () { + expect(argsFor(), [ + '--experimental-expression-compiler', + '--dart-sdk-summary', + 'file:///sdk/ddc_outline.dill', + '--asset-server-address', + 'localhost', + '--asset-server-port', + '1234', + '--module-format', + 'ddc', + '--enable-experiment=records', + '--canary', + ]); + }); + + test('does not pass deprecated-js-interop when not configured', () { + expect(argsFor(), isNot(contains(contains('deprecated-js-interop')))); + }); + + test('passes --deprecated-js-interop', () { + final args = argsFor(deprecatedJsInterop: true); + expect(args, contains('--deprecated-js-interop')); + expect(args, isNot(contains('--no-deprecated-js-interop'))); + }); + + test('passes --no-deprecated-js-interop', () { + final args = argsFor(deprecatedJsInterop: false); + expect(args, contains('--no-deprecated-js-interop')); + expect(args, isNot(contains('--deprecated-js-interop'))); + }); + }); +} From 7cc6d5efdac568deb3958ee1e164885307f274a5 Mon Sep 17 00:00:00 2001 From: Nate Biggs Date: Mon, 5 Oct 2026 15:52:55 -0400 Subject: [PATCH 2/6] Update pubspec with required Dart SDK version --- dwds/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwds/pubspec.yaml b/dwds/pubspec.yaml index 1cebe5fc3e..04453bf114 100644 --- a/dwds/pubspec.yaml +++ b/dwds/pubspec.yaml @@ -7,7 +7,7 @@ description: >- service protocol. repository: https://github.com/dart-lang/webdev/tree/main/dwds environment: - sdk: ^3.13.0-107.0.dev + sdk: ^3.14.0-286.0.dev dependencies: async: ^2.9.0 From 63a92ae36df4e549398a422b7752c353f9e5907f Mon Sep 17 00:00:00 2001 From: Nate Biggs Date: Mon, 5 Oct 2026 16:19:11 -0400 Subject: [PATCH 3/6] Update test --- dwds/test/services/expression_compiler_worker_args_test.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/dwds/test/services/expression_compiler_worker_args_test.dart b/dwds/test/services/expression_compiler_worker_args_test.dart index 79ff56595a..4f5502b9e0 100644 --- a/dwds/test/services/expression_compiler_worker_args_test.dart +++ b/dwds/test/services/expression_compiler_worker_args_test.dart @@ -33,7 +33,6 @@ void main() { '1234', '--module-format', 'ddc', - '--enable-experiment=records', '--canary', ]); }); From 984fb7d489dfcb45bc3a2003bfd702593ad083a8 Mon Sep 17 00:00:00 2001 From: Nate Biggs Date: Tue, 6 Oct 2026 20:20:28 -0400 Subject: [PATCH 4/6] Empty commit From 9923cb5f9b5fc1cdfa951f6dc565d06c59cbfeb2 Mon Sep 17 00:00:00 2001 From: Nate Biggs Date: Wed, 7 Oct 2026 13:39:29 -0400 Subject: [PATCH 5/6] Empty commit From 4506cf9cd356112735998d4ae0c6216742d3c48d Mon Sep 17 00:00:00 2001 From: Nate Biggs Date: Wed, 7 Oct 2026 14:39:49 -0400 Subject: [PATCH 6/6] Fix failing test --- dwds/test/services/expression_compiler_worker_args_test.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/dwds/test/services/expression_compiler_worker_args_test.dart b/dwds/test/services/expression_compiler_worker_args_test.dart index 4f5502b9e0..79ff56595a 100644 --- a/dwds/test/services/expression_compiler_worker_args_test.dart +++ b/dwds/test/services/expression_compiler_worker_args_test.dart @@ -33,6 +33,7 @@ void main() { '1234', '--module-format', 'ddc', + '--enable-experiment=records', '--canary', ]); });