`third_party/node/node_modules` is generated by `./mach vendor node`. Differential Revision: https://phabricator.services.mozilla.com/D320322
170 lines
6.2 KiB
JavaScript
170 lines
6.2 KiB
JavaScript
/*
|
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
|
Author Tobias Koppers @sokra
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
const InitFragment = require("../InitFragment");
|
|
const RuntimeGlobals = require("../RuntimeGlobals");
|
|
const Template = require("../Template");
|
|
const { propertyAccess } = require("../util/property");
|
|
|
|
/** @typedef {import("../ConcatenationScope")} ConcatenationScope */
|
|
/** @typedef {import("../Generator").GenerateContext} GenerateContext */
|
|
/** @typedef {import("../Module")} Module */
|
|
/** @typedef {import("../Module").RuntimeRequirements} RuntimeRequirements */
|
|
/** @typedef {import("../ModuleGraph")} ModuleGraph */
|
|
/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
|
|
/** @typedef {"exports" | "module.exports" | "this" | "Object.defineProperty(exports)" | "Object.defineProperty(module.exports)" | "Object.defineProperty(this)"} CommonJSDependencyBaseKeywords */
|
|
|
|
/**
|
|
* The well-known name of the ESM named export that, when present, is unwrapped
|
|
* by CommonJS `require()` to match Node.js v23+ `require(esm)` semantics:
|
|
* https://nodejs.org/docs/latest/api/modules.html#loading-ecmascript-modules-using-require
|
|
*/
|
|
const ESM_MODULE_EXPORTS_NAME = "module.exports";
|
|
|
|
/**
|
|
* Whether `require()` of `importedModule` would trigger Node.js's
|
|
* `require(esm)` `"module.exports"` named-export unwrap. This is the
|
|
* usage-independent eligibility check: it only looks at module type and
|
|
* whether the export is declared, so it can be safely used from
|
|
* `getReferencedExports` before usage info is finalized (otherwise the
|
|
* check would be circular — we'd need `"module.exports"` to already be
|
|
* marked used in order to ask whether to mark it used).
|
|
* @param {Module} importedModule the imported module
|
|
* @param {ModuleGraph} moduleGraph the module graph
|
|
* @returns {boolean} true if `require()` should unwrap `"module.exports"`
|
|
*/
|
|
const isRequireEsmModuleExportsModule = (importedModule, moduleGraph) => {
|
|
if (importedModule.getExportsType(moduleGraph, false) !== "namespace") {
|
|
return false;
|
|
}
|
|
const exportsInfo = moduleGraph.getExportsInfo(importedModule);
|
|
const exportInfo = exportsInfo.getReadOnlyExportInfo(ESM_MODULE_EXPORTS_NAME);
|
|
return exportInfo.provided === true;
|
|
};
|
|
|
|
/**
|
|
* When CommonJS `require()` resolves to an ES module that has a named export
|
|
* with the literal string name `"module.exports"`, Node.js returns the value of
|
|
* that export instead of the namespace object. Returns the property-access
|
|
* expression to apply to the require result for that unwrapping, or `null` if
|
|
* the imported module is not eligible (not strictly ESM, or no such export,
|
|
* or the export was tree-shaken away).
|
|
* @param {Module} importedModule the imported module
|
|
* @param {ModuleGraph} moduleGraph the module graph
|
|
* @param {RuntimeSpec} runtime the runtime for which the module is analysed
|
|
* @returns {string | null} property-access expression (e.g. `["module.exports"]`), or `null`
|
|
*/
|
|
const getRequireEsmModuleExportsAccess = (
|
|
importedModule,
|
|
moduleGraph,
|
|
runtime
|
|
) => {
|
|
if (!isRequireEsmModuleExportsModule(importedModule, moduleGraph)) {
|
|
return null;
|
|
}
|
|
const exportsInfo = moduleGraph.getExportsInfo(importedModule);
|
|
// CJS exports are never inlined
|
|
const usedName = exportsInfo.getUsedName([ESM_MODULE_EXPORTS_NAME], runtime);
|
|
if (usedName === false) return null;
|
|
return propertyAccess(/** @type {readonly string[]} */ (usedName));
|
|
};
|
|
|
|
module.exports.ESM_MODULE_EXPORTS_NAME = ESM_MODULE_EXPORTS_NAME;
|
|
|
|
/**
|
|
* Rewrites an `exports.<names>` reference of a concatenated CommonJS module to
|
|
* a hoisted module-scope variable and registers that variable as the export's
|
|
* symbol, so other concatenated modules bind to it directly.
|
|
* @param {ConcatenationScope} concatenationScope the concatenation scope
|
|
* @param {InitFragment<GenerateContext>[]} initFragments init fragments (receives the `var` declaration)
|
|
* @param {string[]} names full member chain of the reference (at least one entry)
|
|
* @returns {string} replacement expression for the whole reference
|
|
*/
|
|
module.exports.getConcatenatedExportAccess = (
|
|
concatenationScope,
|
|
initFragments,
|
|
names
|
|
) => {
|
|
const name = names[0];
|
|
const identifier = Template.toIdentifier(name);
|
|
// A sanitized name could collide with another export ("a-b" vs "a_b"),
|
|
// so non-identifier names get a hex suffix of the raw name.
|
|
const symbol = `__WEBPACK_CJS_EXPORT_${
|
|
identifier === name
|
|
? name
|
|
: `${identifier}_${Buffer.from(name, "utf8").toString("hex")}`
|
|
}__`;
|
|
initFragments.push(
|
|
new InitFragment(
|
|
`var ${symbol};\n`,
|
|
InitFragment.STAGE_CONSTANTS,
|
|
0,
|
|
`cjs concatenated export ${name}`
|
|
)
|
|
);
|
|
concatenationScope.registerExport(name, symbol);
|
|
return `${symbol}${propertyAccess(names, 1)}`;
|
|
};
|
|
module.exports.getRequireEsmModuleExportsAccess =
|
|
getRequireEsmModuleExportsAccess;
|
|
|
|
/**
|
|
* Returns type and base.
|
|
* @param {CommonJSDependencyBaseKeywords} depBase commonjs dependency base
|
|
* @param {Module} module module
|
|
* @param {RuntimeRequirements} runtimeRequirements runtime requirements
|
|
* @returns {[string, string]} type and base
|
|
*/
|
|
module.exports.handleDependencyBase = (
|
|
depBase,
|
|
module,
|
|
runtimeRequirements
|
|
) => {
|
|
/** @type {string} */
|
|
let base;
|
|
/** @type {string} */
|
|
let type;
|
|
switch (depBase) {
|
|
case "exports":
|
|
runtimeRequirements.add(RuntimeGlobals.exports);
|
|
base = module.exportsArgument;
|
|
type = "expression";
|
|
break;
|
|
case "module.exports":
|
|
runtimeRequirements.add(RuntimeGlobals.module);
|
|
base = `${module.moduleArgument}.exports`;
|
|
type = "expression";
|
|
break;
|
|
case "this":
|
|
runtimeRequirements.add(RuntimeGlobals.thisAsExports);
|
|
base = "this";
|
|
type = "expression";
|
|
break;
|
|
case "Object.defineProperty(exports)":
|
|
runtimeRequirements.add(RuntimeGlobals.exports);
|
|
base = module.exportsArgument;
|
|
type = "Object.defineProperty";
|
|
break;
|
|
case "Object.defineProperty(module.exports)":
|
|
runtimeRequirements.add(RuntimeGlobals.module);
|
|
base = `${module.moduleArgument}.exports`;
|
|
type = "Object.defineProperty";
|
|
break;
|
|
case "Object.defineProperty(this)":
|
|
runtimeRequirements.add(RuntimeGlobals.thisAsExports);
|
|
base = "this";
|
|
type = "Object.defineProperty";
|
|
break;
|
|
default:
|
|
throw new Error(`Unsupported base ${depBase}`);
|
|
}
|
|
|
|
return [type, base];
|
|
};
|
|
module.exports.isRequireEsmModuleExportsModule =
|
|
isRequireEsmModuleExportsModule;
|