link = (
  { entry, compartments: compartmentDescriptors },
  options,
) => {
  const {
    resolve = resolveFallback,
    makeImportHook,
    makeImportNowHook = impossibleImportNowHookMaker,
    parserForLanguage: parserForLanguageOption = {},
    globals = {},
    transforms = [],
    moduleTransforms,
    syncModuleTransforms,
    __shimTransforms__ = [],
    __native__ = false,
    archiveOnly = false,
    Compartment = defaultCompartment,
  } = options;

  const { compartment: entryCompartmentName } = entry;

  /** @type {Record<string, Compartment>} */
  const compartments = create(null);

  /**
   * @param {string} attenuatorSpecifier
   */
  const attenuators = makeDeferredAttenuatorsProvider(
    compartments,
    compartmentDescriptors,
  );

  const pendingJobs = [];

  /** @type {ParserForLanguage} */
  const parserForLanguage = freeze(
    assign(create(null), parserForLanguageOption),
  );

  const mapParsers = makeMapParsers({
    parserForLanguage,
    moduleTransforms,
    syncModuleTransforms,
  });

  for (const [compartmentName, compartmentDescriptor] of entries(
    compartmentDescriptors,
  )) {
    const {
      location,
      name,
      parsers: languageForExtension = {},
      types: languageForModuleSpecifier = {},
    } = compartmentDescriptor;

    // this is for retaining the correct type inference about these values
    // without use of `let`
    const { scopes: _scopes, modules: _modules } = compartmentDescriptor;
    const modules = _modules || create(null);
    const scopes = _scopes || create(null);

    // Capture the default.
    // The `moduleMapHook` writes back to the compartment map.
    compartmentDescriptor.modules = modules;

    // TS is kind of dumb about this, so we can use a type assertion to avoid a
    // pointless ternary.
    const parse = /** @type {ParseFn|AsyncParseFn} */ (
      mapParsers(languageForExtension, languageForModuleSpecifier)
    );

    /** @type {ShouldDeferError} */
    const shouldDeferError = language => {
      if (language && has(parserForLanguage, language)) {
        return /** @type {ParserImplementation} */ (parserForLanguage[language])
          .heuristicImports;
      } else {
        // If language is undefined or there's no parser, the error we could consider deferring is surely related to
        // that. Nothing to throw here.
        return false;
      }
    };

    // If we ever need an alternate resolution algorithm, it should be
    // indicated in the compartment descriptor and a behavior selected here.
    const resolveHook = resolve;
    const importHook = makeImportHook({
      packageLocation: location,
      packageName: name,
      attenuators,
      parse,
      shouldDeferError,
      compartments,
    });

    const importNowHook = makeImportNowHook({
      packageLocation: location,
      packageName: name,
      parse,
      compartments,
      shouldDeferError,
    });

    const moduleMapHook = makeModuleMapHook(
      compartmentDescriptor,
      compartments,
      compartmentName,
      modules,
      scopes,
    );

    const compartment = new Compartment({
      name: location,
      resolveHook,
      importHook,
      importNowHook,
      moduleMapHook,
      transforms,
      __shimTransforms__,
      __options__: true,
      __native__,
    });

    if (!archiveOnly) {
      attenuateGlobals(
        compartment.globalThis,
        globals,
        compartmentDescriptor.policy,
        attenuators,
        pendingJobs,
        compartmentDescriptor.name,
      );
    }

    compartments[compartmentName] = compartment;
  }

  const compartment = compartments[entryCompartmentName];
  if (compartment === undefined) {
    throw Error(
      `Cannot assemble compartment graph because the root compartment named ${q(
        entryCompartmentName,
      )} is missing from the compartment map`,
    );
  }
  const attenuatorsCompartment = compartments[ATTENUATORS_COMPARTMENT];

  return {
    compartment,
    compartments,
    attenuatorsCompartment,
    pendingJobsPromise: promiseAllSettled(pendingJobs).then(
      /** @param {PromiseSettledResult<unknown>[]} results */ results => {
        const errors = results
          .filter(result => result.status === 'rejected')
          .map(
            /** @param {PromiseRejectedResult} result */ result =>
              result.reason,
          );
        if (errors.length > 0) {
          throw Error(
            `Globals attenuation errors: ${errors
              .map(error => error.message)
              .join(', ')}`,
          );
        }
      },
    ),
  };
}
@param {CompartmentMapDescriptor} compartmentMap
@param {LinkOptions} options
@returns {LinkResult}