[webdev] Add a flag used to preview the new DDC module bundle format (#2794)

We're planning on swapping to the DDC Library Bundle module format by default (with the end goal of deprecating AMD). This adds a flag for easy testing/swapping between the module formats during the migration period.
diff --git a/webdev/CHANGELOG.md b/webdev/CHANGELOG.md
index be7d14c..250c456 100644
--- a/webdev/CHANGELOG.md
+++ b/webdev/CHANGELOG.md
@@ -1,4 +1,6 @@
-## 3.8.2-wip
+## 3.8.2
+
+- Add `module-format` flag for testing new DDC Library Bundle module format prior to release.
 
 ## 3.8.1
 
diff --git a/webdev/lib/src/command/configuration.dart b/webdev/lib/src/command/configuration.dart
index 27b67d6..dac2256 100644
--- a/webdev/lib/src/command/configuration.dart
+++ b/webdev/lib/src/command/configuration.dart
@@ -37,6 +37,7 @@
 const disableDdsFlag = 'disable-dds';
 const enableExperimentOption = 'enable-experiment';
 const canaryFeaturesFlag = 'canary';
+const moduleFormatFlag = 'module-format';
 const offlineFlag = 'offline';
 
 ReloadConfiguration _parseReloadConfiguration(ArgResults argResults) {
@@ -111,6 +112,7 @@
   final String? _nullSafety;
   final List<String>? _experiments;
   final bool? _canaryFeatures;
+  final String? _moduleFormat;
   final bool? _offline;
 
   Configuration({
@@ -138,6 +140,7 @@
     String? nullSafety,
     List<String>? experiments,
     bool? canaryFeatures,
+    String? moduleFormat,
     bool? offline,
   }) : _autoRun = autoRun,
        _chromeDebugPort = chromeDebugPort,
@@ -161,6 +164,7 @@
        _nullSafety = nullSafety,
        _experiments = experiments,
        _canaryFeatures = canaryFeatures,
+       _moduleFormat = moduleFormat,
        _offline = offline {
     _validateConfiguration();
   }
@@ -245,6 +249,7 @@
     nullSafety: other._nullSafety ?? _nullSafety,
     experiments: other._experiments ?? _experiments,
     canaryFeatures: other._canaryFeatures ?? _canaryFeatures,
+    moduleFormat: other._moduleFormat ?? _moduleFormat,
     offline: other._offline ?? _offline,
   );
 
@@ -301,6 +306,10 @@
 
   bool get canaryFeatures => _canaryFeatures ?? false;
 
+  String get moduleFormat => _moduleFormat ?? 'amd';
+
+  bool get usesDdcLibraryBundle => canaryFeatures || (moduleFormat == 'ddc');
+
   bool get offline => _offline ?? false;
 
   /// Returns a new configuration with values updated from the parsed args.
@@ -433,6 +442,10 @@
         ? argResults[canaryFeaturesFlag] as bool?
         : defaultConfiguration.canaryFeatures;
 
+    final moduleFormat = argResults.options.contains(moduleFormatFlag)
+        ? argResults[moduleFormatFlag] as String?
+        : defaultConfiguration.moduleFormat;
+
     final offline = argResults.options.contains(offlineFlag)
         ? argResults[offlineFlag] as bool?
         : defaultConfiguration.verbose;
@@ -462,6 +475,7 @@
       nullSafety: nullSafety,
       experiments: experiments,
       canaryFeatures: canaryFeatures,
+      moduleFormat: moduleFormat,
       offline: offline,
     );
   }
diff --git a/webdev/lib/src/command/shared.dart b/webdev/lib/src/command/shared.dart
index 132009c..cf79fb1 100644
--- a/webdev/lib/src/command/shared.dart
+++ b/webdev/lib/src/command/shared.dart
@@ -89,6 +89,13 @@
       hide: true,
       help: 'Enables DDC canary features.',
     )
+    ..addOption(
+      moduleFormatFlag,
+      defaultsTo: 'amd',
+      allowed: ['amd', 'ddc'],
+      help: 'Sets the module format DDC uses for compilation.',
+      hide: true,
+    )
     ..addFlag(
       verboseFlag,
       abbr: 'v',
@@ -144,6 +151,21 @@
       ..add('build_web_compilers|ddc_modules=web-hot-reload=true');
   }
 
+  if (configuration.moduleFormat == 'ddc') {
+    arguments
+      ..add('--define')
+      ..add('build_web_compilers|ddc=ddc-library-bundle=true');
+    arguments
+      ..add('--define')
+      ..add('build_web_compilers|sdk_js=ddc-library-bundle=true');
+    arguments
+      ..add('--define')
+      ..add('build_web_compilers|entrypoint=ddc-library-bundle=true');
+    arguments
+      ..add('--define')
+      ..add('build_web_compilers|entrypoint_marker=ddc-library-bundle=true');
+  }
+
   return arguments;
 }
 
diff --git a/webdev/lib/src/serve/webdev_server.dart b/webdev/lib/src/serve/webdev_server.dart
index e3b4f55..fbbaab1 100644
--- a/webdev/lib/src/serve/webdev_server.dart
+++ b/webdev/lib/src/serve/webdev_server.dart
@@ -121,7 +121,7 @@
 
     // Only provide relevant build results
     final filteredBuildResults = buildResults.asyncMap<BuildResult>((results) {
-      if (options.configuration.canaryFeatures) {
+      if (options.configuration.usesDdcLibraryBundle) {
         // Clear reloaded sources for the new build results.
         reloadedSources.clear();
         results.changedAssets?.forEach((uri) {
@@ -203,12 +203,22 @@
           injectScriptLoad: false,
         ).strategy;
       } else {
-        loadStrategy = BuildRunnerRequireStrategyProvider(
-          options.configuration.reload,
-          assetReader,
-          buildSettings,
-          packageConfigPath: findPackageConfigFilePath(),
-        ).strategy;
+        if (options.configuration.moduleFormat == 'ddc') {
+          loadStrategy = BuildRunnerDdcLibraryBundleStrategyProvider(
+            options.configuration.reload,
+            assetReader,
+            buildSettings,
+            packageConfigPath: findPackageConfigFilePath(),
+            reloadedSourcesUri: Uri.parse('$basePath/$reloadedSourcesFileName'),
+          ).strategy;
+        } else {
+          loadStrategy = BuildRunnerRequireStrategyProvider(
+            options.configuration.reload,
+            assetReader,
+            buildSettings,
+            packageConfigPath: findPackageConfigFilePath(),
+          ).strategy;
+        }
       }
 
       if (options.configuration.enableExpressionEvaluation) {
@@ -248,7 +258,7 @@
       );
       pipeline = pipeline.addMiddleware(dwds.middleware);
       cascade = cascade.add(dwds.handler);
-      if (options.configuration.canaryFeatures) {
+      if (options.configuration.usesDdcLibraryBundle) {
         // Add a handler to serve reloaded sources.
         cascade = cascade.add((Request request) {
           if (request.url.path == reloadedSourcesFileName) {
diff --git a/webdev/lib/src/version.dart b/webdev/lib/src/version.dart
index 550cb31..1ef2b2b 100644
--- a/webdev/lib/src/version.dart
+++ b/webdev/lib/src/version.dart
@@ -1,2 +1,2 @@
 // Generated code. Do not modify.
-const packageVersion = '3.8.2-wip';
+const packageVersion = '3.8.2';
diff --git a/webdev/pubspec.yaml b/webdev/pubspec.yaml
index 3a31ebb..bceeda2 100644
--- a/webdev/pubspec.yaml
+++ b/webdev/pubspec.yaml
@@ -1,6 +1,6 @@
 name: webdev
 # Every time this changes you need to run `dart run build_runner build`.
-version: 3.8.2-wip
+version: 3.8.2
 # We should not depend on a dev SDK before publishing.
 # publish_to: none
 description: >-