function makeImportNowHookMaker(
  readPowers,
  baseLocation,
  {
    sources = create(null),
    compartmentDescriptors = create(null),
    computeSha512 = undefined,
    searchSuffixes = nodejsConventionSearchSuffixes,
    archiveOnly = false,
    sourceMapHook = undefined,
    importNowHook: exitModuleImportNowHook = undefined,
  },
) {
  // Set of specifiers for modules (scoped to compartment) whose parser is not
  // using heuristics to determine imports.
  /** @type {Map<string, Set<string>>} compartment name ->* module specifier */
  const strictlyRequired = new Map();

  /**
   * @param {string} compartmentName
   */
  const strictlyRequiredForCompartment = compartmentName => {
    let compartmentStrictlyRequired = strictlyRequired.get(compartmentName);
    if (compartmentStrictlyRequired !== undefined) {
      return compartmentStrictlyRequired;
    }
    compartmentStrictlyRequired = new Set();
    strictlyRequired.set(compartmentName, compartmentStrictlyRequired);
    return compartmentStrictlyRequired;
  };

  /**
   * @type {ImportNowHookMaker}
   */
  const makeImportNowHook = ({
    packageLocation,
    packageName: _packageName,
    parse,
    compartments,
    shouldDeferError,
  }) => {
    const deferError = makeDeferError(
      strictlyRequiredForCompartment,
      packageLocation,
      sources,
    );

    /**
     * Attempt to load the moduleSpecifier via an {@link ExitModuleImportNowHook}, if one exists.
     *
     * If it doesn't exist, then throw an exception.
     * @param {string} moduleSpecifier
     * @param {CompartmentDescriptor} compartmentDescriptor
     * @returns {VirtualModuleSource}
     */
    const importExitModuleOrFail = (moduleSpecifier, compartmentDescriptor) => {
      if (exitModuleImportNowHook) {
        // This hook is responsible for ensuring that the moduleSpecifier
        // actually refers to an exit module.
        const exitRecord = exitModuleImportNowHook(
          moduleSpecifier,
          packageLocation,
        );
        if (exitRecord) {
          // It'd be nice to check the policy before importing it, but we can only throw a policy error if the
          // hook returns something. Otherwise, we need to fall back to the 'cannot find' error below.
          enforceModulePolicy(moduleSpecifier, compartmentDescriptor, {
            exit: true,
            errorHint: `Blocked in loading. ${q(
              moduleSpecifier,
            )} was not in the compartment map and an attempt was made to load it as a builtin`,
          });
          return exitRecord;
        }
        throw Error(
          `Cannot find external module ${q(
            moduleSpecifier,
          )} in package at ${packageLocation}`,
        );
      } else {
        throw Error(
          `Cannot find external module ${q(
            moduleSpecifier,
          )} from package at ${packageLocation}; try providing an importNowHook`,
        );
      }
    };

    if (!('isSyncParser' in parse)) {
      return function impossibleTransformImportNowHook() {
        throw new Error(
          'Dynamic requires are only possible with synchronous parsers and no asynchronous module transforms in options',
        );
      };
    }

    const compartmentDescriptor = compartmentDescriptors[packageLocation] || {};

    packageLocation = resolveLocation(packageLocation, baseLocation);
    const packageSources = sources[packageLocation] || create(null);
    sources[packageLocation] = packageSources;
    const {
      modules:
        moduleDescriptors = /** @type {Record<string, ModuleDescriptor>} */ (
          create(null)
        ),
    } = compartmentDescriptor;
    compartmentDescriptor.modules = moduleDescriptors;

    let { policy } = compartmentDescriptor;
    policy = policy || create(null);

    // Associates modules with compartment descriptors based on policy
    // in cases where the association was not made when building the
    // compartment map but is indicated by the policy.
    if ('packages' in policy && typeof policy.packages === 'object') {
      for (const [packageName, packagePolicyItem] of entries(policy.packages)) {
        if (
          !(packageName in compartmentDescriptor.modules) &&
          packageName in compartmentDescriptor.scopes &&
          packagePolicyItem
        ) {
          compartmentDescriptor.modules[packageName] =
            compartmentDescriptor.scopes[packageName];
        }
      }
    }

    const { maybeReadNow, isAbsolute } = readPowers;

    /** @type {ImportNowHook} */
    const importNowHook = moduleSpecifier => {
      try {
        // many dynamically-required specifiers will be absolute paths owing to use of `require.resolve()` and `path.resolve()`
        if (isAbsolute(moduleSpecifier)) {
          const record = findRedirect({
            compartmentDescriptor,
            compartmentDescriptors,
            compartments,
            absoluteModuleSpecifier: moduleSpecifier,
          });
          if (record) {
            return record;
          }

          // if and only if the module specifier is within the compartment can we
          // make it a relative specifier. the following conditional avoids a try/catch
          // since `relativeSpecifier` will throw if this condition is not met
          if (
            isLocationWithinCompartment(
              moduleSpecifier,
              compartmentDescriptor.location,
            )
          ) {
            moduleSpecifier = relativeSpecifier(
              moduleSpecifier,
              compartmentDescriptor.location,
            );
          }
        } else if (
          moduleSpecifier !== '.' &&
          !moduleSpecifier.startsWith('./')
        ) {
          // could be a builtin, which means we should not bother bouncing on the trampoline to find it.
          return importExitModuleOrFail(moduleSpecifier, compartmentDescriptor);
        }

        // we might have an absolute path here, but it might be within the compartment, so
        // we will try to find it.
        const candidates = nominateCandidates(moduleSpecifier, searchSuffixes);

        const record = syncTrampoline(
          chooseModuleDescriptor,
          {
            candidates,
            compartmentDescriptor,
            compartmentDescriptors,
            compartments,
            computeSha512,
            moduleDescriptors,
            moduleSpecifier,
            packageLocation,
            packageSources,
            readPowers,
            archiveOnly,
            sourceMapHook,
            strictlyRequiredForCompartment,
          },
          {
            maybeRead: maybeReadNow,
            parse,
            shouldDeferError,
          },
        );

        if (record) {
          return record;
        }

        // at this point, we haven't found the module by guessing, so we'll try the importer-of-last-resort
        return importExitModuleOrFail(moduleSpecifier, compartmentDescriptor);
      } catch (err) {
        return deferError(moduleSpecifier, err);
      }
    };
    return importNowHook;
  };
  return makeImportNowHook;
}
Synchronous import for dynamic requires.

@param {ReadNowPowers} readPowers
@param {string} baseLocation
@param {MakeImportNowHookMakerOptions} options
@returns {ImportNowHookMaker}