Future bootstrapDdc()

in build_web_compilers/lib/src/dev_compiler_bootstrap.dart [30:159]


Future<void> bootstrapDdc(
  BuildStep buildStep, {
  DartPlatform? platform,
  Iterable<AssetId> requiredAssets = const [],
  required bool soundNullSafety,
  required bool nativeNullAssertions,
  required bool nullAssertions,
}) async {
  platform = ddcPlatform;
  // Ensures that the sdk resources are built and available.
  await _ensureResources(buildStep, requiredAssets);

  var dartEntrypointId = buildStep.inputId;
  var moduleId = buildStep.inputId.changeExtension(moduleExtension(platform));
  var module = Module.fromJson(json
      .decode(await buildStep.readAsString(moduleId)) as Map<String, dynamic>);

  // First, ensure all transitive modules are built.
  List<AssetId> transitiveJsModules;
  try {
    transitiveJsModules = await _ensureTransitiveJsModules(module, buildStep,
        soundNullSafety: soundNullSafety);
  } on UnsupportedModules catch (e) {
    var librariesString = (await e.exactLibraries(buildStep).toList())
        .map((lib) => AssetId(lib.id.package,
            lib.id.path.replaceFirst(moduleLibraryExtension, '.dart')))
        .join('\n');
    log.warning('''
Skipping compiling ${buildStep.inputId} with ddc because some of its
transitive libraries have sdk dependencies that not supported on this platform:

$librariesString

https://github.com/dart-lang/build/blob/master/docs/faq.md#how-can-i-resolve-skipped-compiling-warnings
''');
    return;
  }
  var jsId =
      module.primarySource.changeExtension(jsModuleExtension(soundNullSafety));
  var appModuleName = ddcModuleName(jsId, soundNullSafety);
  var appDigestsOutput =
      dartEntrypointId.changeExtension(digestsEntrypointExtension);
  var mergedMetadataOutput =
      dartEntrypointId.changeExtension(mergedMetadataExtension);

  // The name of the entrypoint dart library within the entrypoint JS module.
  //
  // This is used to invoke `main()` from within the bootstrap script.
  //
  // TODO(jakemac53): Sane module name creation, this only works in the most
  // basic of cases.
  //
  // See https://github.com/dart-lang/sdk/issues/27262 for the root issue
  // which will allow us to not rely on the naming schemes that dartdevc uses
  // internally, but instead specify our own.
  var oldAppModuleScope = toJSIdentifier(
      _context.withoutExtension(_context.basename(buildStep.inputId.path)));

  // Like above but with a package-relative entrypoint.
  var appModuleScope =
      pathToJSIdentifier(_context.withoutExtension(buildStep.inputId.path));

  // Map from module name to module path for custom modules.
  var modulePaths = SplayTreeMap.of({
    'dart_sdk': r'packages/build_web_compilers/src/dev_compiler/dart_sdk'
        '${soundNullSafety ? '.sound' : ''}'
  });
  for (var jsId in transitiveJsModules) {
    // Strip out the top level dir from the path for any module, and set it to
    // `packages/` for lib modules. We set baseUrl to `/` to simplify things,
    // and we only allow you to serve top level directories.
    var moduleName = ddcModuleName(jsId, soundNullSafety);
    modulePaths[moduleName] = _context.withoutExtension(
        jsId.path.startsWith('lib')
            ? '$moduleName${jsModuleExtension(soundNullSafety)}'
            : _context.joinAll(_context.split(jsId.path).skip(1)));
  }

  var bootstrapId = dartEntrypointId.changeExtension(ddcBootstrapExtension);
  var bootstrapModuleName = _context.withoutExtension(_context.relative(
      bootstrapId.path,
      from: _context.dirname(dartEntrypointId.path)));

  var dartEntrypointParts = _context.split(dartEntrypointId.path);
  var entrypointLibraryName = _context.joinAll([
    // Convert to a package: uri for files under lib.
    if (dartEntrypointParts.first == 'lib')
      'package:${module.primarySource.package}',
    // Strip top-level directory from the path.
    ...dartEntrypointParts.skip(1),
  ]);

  var bootstrapContent =
      StringBuffer('$_entrypointExtensionMarker\n(function() {\n')
        ..write(_dartLoaderSetup(
            modulePaths,
            _p.url.relative(appDigestsOutput.path,
                from: _p.url.dirname(bootstrapId.path)),
            soundNullSafety))
        ..write(_requireJsConfig(soundNullSafety))
        ..write(_appBootstrap(
            bootstrapModuleName: bootstrapModuleName,
            entrypointLibraryName: entrypointLibraryName,
            moduleName: appModuleName,
            moduleScope: appModuleScope,
            nativeNullAssertions: nativeNullAssertions,
            nullAssertions: nullAssertions,
            oldModuleScope: oldAppModuleScope));

  await buildStep.writeAsString(bootstrapId, bootstrapContent.toString());

  var entrypointJsContent = _entryPointJs(bootstrapModuleName);
  await buildStep.writeAsString(
      dartEntrypointId.changeExtension(jsEntrypointExtension),
      entrypointJsContent);

  // Output the digests and merged_metadata for transitive modules.
  // These can be consumed for hot reloads and debugging.
  var mergedMetadataContent = StringBuffer();
  var moduleDigests = <String, String>{};
  for (var jsId in transitiveJsModules) {
    mergedMetadataContent.writeln(
        await buildStep.readAsString(jsId.changeExtension('.js.metadata')));
    moduleDigests[_moduleDigestKey(jsId, soundNullSafety)] =
        '${await buildStep.digest(jsId)}';
  }
  await buildStep.writeAsString(appDigestsOutput, jsonEncode(moduleDigests));
  await buildStep.writeAsString(
      mergedMetadataOutput, mergedMetadataContent.toString());
}