Repository: parcel-bundler/parcel
File: packages/packagers/js/src/ScopeHoistingPackager.js (JavaScript)

Code before:
      )}, function(module, exports) {
${code}
});
`;

      lineCount += 2;

      for (let [depCode, map, lines] of depContent) {
        if (!depCode) continue;
        code += depCode + '\n';
        if (sourceMap && map) {
          sourceMap.addSourceMap(map, lineCount);
        }
        lineCount += lines + 1;
      }

      this.needsPrelude = true;
    }

    if (this.bundle.env.isNode() && asset.meta.has_node_replacements) {
      const relPath = normalizeSeparators(
        path.relative(this.bundle.target.distDir, path.dirname(asset.filePath)),
      );
      code = code.replace('$parcel$dirnameReplace', relPath);
      code = code.replace('$parcel$filenameReplace', relPath);
    }

    return [code, sourceMap, lineCount];
  }

  buildReplacements(
    asset: Asset,
    deps: Array<Dependency>,
  ): [Map<string, Dependency>, Map<string, string>] {
    let assetId = asset.meta.id;
    invariant(typeof assetId === 'string');

    // Build two maps: one of import specifiers, and one of imported symbols to replace.
    // These will be used to build a regex below.
    let depMap = new Map();
    let replacements = new Map();
    for (let dep of deps) {
      depMap.set(`${assetId}:${getSpecifier(dep)}`, dep);

      let asyncResolution = this.bundleGraph.resolveAsyncDependency(
        dep,
        this.bundle,
      );
      let resolved =
        asyncResolution?.type === 'asset'
          ? // Prefer the underlying asset over a runtime to load it. It will

Review comment (bug):
This should happen further up in this function (e.g. near `if (code.includes('$parcel$global'))`) because there are recursive calls inside `buildAsset` where it inlines dependencies. Right now, `code` might contain the code for multiple assets and then `asset.filePath` is wrong.

Code after:
    // wrapper. Dependencies must be inserted AFTER the asset is registered so that circular dependencies work.
    if (shouldWrap) {
      // Offset by one line for the parcelRequire.register wrapper.
      sourceMap?.offsetLines(1, 1);
      lineCount++;

      code = `parcelRequire.register(${JSON.stringify(
        this.bundleGraph.getAssetPublicId(asset),
      )}, function(module, exports) {
${code}
});
`;

      lineCount += 2;

      for (let [depCode, map, lines] of depContent) {
        if (!depCode) continue;
        code += depCode + '\n';
        if (sourceMap && map) {
          sourceMap.addSourceMap(map, lineCount);
        }
        lineCount += lines + 1;
      }

      this.needsPrelude = true;
    }

    return [code, sourceMap, lineCount];
  }

  buildReplacements(
    asset: Asset,
    deps: Array<Dependency>,
  ): [Map<string, Dependency>, Map<string, string>] {
    let assetId = asset.meta.id;
    invariant(typeof assetId === 'string');

    // Build two maps: one of import specifiers, and one of imported symbols to replace.
    // These will be used to build a regex below.
    let depMap = new Map();
    let replacements = new Map();
    for (let dep of deps) {
      depMap.set(`${assetId}:${getSpecifier(dep)}`, dep);

      let asyncResolution = this.bundleGraph.resolveAsyncDependency(
        dep,
        this.bundle,
      );
      let resolved =
        asyncResolution?.type === 'asset'
          ? // Prefer the underlying asset over a runtime to load it. It will