Files

90 lines
5.2 KiB
JavaScript

const path = require("node:path");
const show = (label, ...values) => console.log(label + " " + JSON.stringify(values));
const names = (mod) => mod.children.map((child) => path.basename(child.filename));
const atLoad = { loaded: module.loaded, cached: require.cache[__filename] === module,
parent: module.parent, children: module.children.length, thisIsExports: this === exports };
exports.report = () => {
show("metadata", module.id === __filename, module.filename === __filename,
module.path === __dirname, module.loaded, module.isPreloading, atLoad.loaded,
atLoad.cached, atLoad.children, atLoad.thisIsExports);
show("fields", Object.keys(module), Object.hasOwn(module, "parent"),
Object.hasOwn(module, "require"), typeof module.require, module.parent === atLoad.parent);
show("paths", module.paths[0] === path.join(__dirname, "node_modules"),
module.paths.filter((item) => item.includes("node_modules/node_modules")).length,
module.paths.at(-1), module.paths.every((item) => path.isAbsolute(item)),
new Set(module.paths).size === module.paths.length);
const a = require("./a.cjs");
show("a", a.atLoad, a.module.parent === module, a.module.loaded,
require.cache[require.resolve("./a.cjs")] === a.module, names(module));
const b = require("./b.cjs");
show("cached-children", names(module), names(a.module), names(b.module),
a.shared === b.shared, a.shared.module.parent === a.module,
b.module.parent === module);
require("./a.cjs");
module.require("./a.cjs");
show("deduplicate", names(module));
const onlyMethod = module.require("./method-only.cjs");
show("module-require", onlyMethod.value, onlyMethod.module.parent === module,
onlyMethod.module.loaded, names(module));
const boundRequire = module.require.bind(module);
show("bound-require", boundRequire("./method-only.cjs") === onlyMethod,
module["require"]("./method-only.cjs") === onlyMethod,
module.require("node:path") === path, names(module));
const cycle = require("./cycle-a.cjs");
show("cycle", cycle.seenByB, cycle.bLoaded, cycle.module.loaded,
cycle.b.module.loaded, names(cycle.module), names(cycle.b.module),
cycle.b.module.parent === cycle.module, cycle.module.parent === module);
const json = require("./data.json");
const jsonModule = require.cache[require.resolve("./data.json")];
show("json", json.answer, jsonModule.exports === json, jsonModule.loaded,
jsonModule.parent === module, jsonModule.filename.endsWith("/data.json"),
jsonModule.children, jsonModule.paths[0] === path.join(__dirname, "node_modules"));
// A failed module is removed, while dependencies successfully loaded by it stay cached.
for (let attempt = 0; attempt < 2; attempt++) {
try { require("./failure.cjs"); } catch (error) {
show("failed-load", error.message, require.cache[require.resolve("./failure.cjs")] === undefined,
names(module).includes("failure.cjs"));
}
}
const survived = require("./survived.cjs");
show("surviving-child", survived.module.loaded, survived.module.parent.loaded,
path.basename(survived.module.parent.filename), names(survived.module.parent),
survived.module.parent.children.includes(survived.module), names(module).includes("survived.cjs"));
show("surviving-stack", survived.missingStack(), survived.missingStack(true));
// Removing an entry and loading it again creates a distinct module without detaching the old one.
const first = require("./reload.cjs");
delete require.cache[require.resolve("./reload.cjs")];
const second = require("./reload.cjs");
show("reload", first !== second, first.module !== second.module,
first.module.parent === module, second.module.parent === module,
names(module).filter((name) => name === "reload.cjs").length);
// createRequire builds a synthetic parent separate from the live module/cache entry.
const creator = require("./creating.cjs");
const { created, syntheticChild } = creator.load();
const synthetic = syntheticChild.module.parent;
show("create-parent", synthetic.id === creator.module.filename, synthetic.filename === creator.module.filename,
synthetic.path === __dirname, synthetic.loaded, synthetic.parent === undefined,
synthetic !== creator.module, synthetic.children[0] === syntheticChild.module,
synthetic.paths[0] === path.join(__dirname, "node_modules"),
creator.again(created) === syntheticChild, synthetic.children.length,
names(module).includes("created.cjs"));
show("synthetic-stack", syntheticChild.missingStack());
const originalParent = syntheticChild.module.parent;
syntheticChild.module.parent = module;
show("set-parent", syntheticChild.module.parent === module, syntheticChild.missingStack(),
originalParent.children.includes(syntheticChild.module), names(module).includes("created.cjs"));
syntheticChild.module.parent = originalParent;
const errors = (fn) => { try { fn(); return ["did-not-throw"]; }
catch (error) { return [error.name, error.code, error.message]; } };
for (const id of [undefined, null, 0, false, {}, ""]) {
show("require-errors", id, errors(() => module.require(id)), errors(() => require(id)));
}
const missing = errors(() => module.require("commonjs-fixture-missing-package"));
show("missing", missing[0], missing[1], missing[2].split("\n")[0]);
};