Files
upstream-zulip/web/debug-require-webpack-plugin.ts
upstream-mirror 64898b2c79
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
2026-09-15 15:05:30 +05:00

126 lines
5.3 KiB
TypeScript

// This plugin exposes a version of require() to the browser console to assist
// debugging. It also exposes the list of modules it knows about as the keys
// of the require.ids object.
import path from "node:path";
import webpack from "webpack";
export default class DebugRequirePlugin implements webpack.WebpackPluginInstance {
apply(compiler: webpack.Compiler): void {
const resolved = new Map<string, Set<string>>();
const nameSymbol = Symbol("DebugRequirePluginName");
type NamedRequest = {
[nameSymbol]?: string | undefined;
};
let debugRequirePath: string | false = false;
compiler.resolverFactory.hooks.resolver
.for("normal")
.tap("DebugRequirePlugin", (resolver) => {
resolver.getHook("beforeRawModule").tap("DebugRequirePlugin", (req) => {
if (!Object.hasOwn(req, nameSymbol)) {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
(req as NamedRequest)[nameSymbol] = req.request;
}
return undefined!;
});
resolver.getHook("beforeRelative").tap("DebugRequirePlugin", (req) => {
if (req.path !== false) {
const inPath = path.relative(compiler.context, req.path);
if (!inPath.startsWith("../") && !Object.hasOwn(req, nameSymbol)) {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
(req as NamedRequest)[nameSymbol] = "./" + inPath;
}
}
return undefined!;
});
resolver.getHook("beforeResolved").tap("DebugRequirePlugin", (req) => {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const name = (req as NamedRequest)[nameSymbol];
if (name !== undefined && req.path !== false) {
const names = resolved.get(req.path);
if (names) {
names.add(name);
} else {
resolved.set(req.path, new Set([name]));
}
}
return undefined!;
});
});
compiler.hooks.beforeCompile.tapPromise(
"DebugRequirePlugin",
async ({normalModuleFactory}) => {
const resolver = normalModuleFactory.getResolver("normal");
debugRequirePath = await new Promise((resolve) => {
resolver.resolve(
{},
import.meta.dirname,
"./debug-require.cjs",
{},
(err?: Error | null, result?: string | false) => {
resolve(err ? false : result!);
},
);
});
},
);
compiler.hooks.compilation.tap("DebugRequirePlugin", (compilation) => {
compilation.mainTemplate.hooks.bootstrap.tap(
"DebugRequirePlugin",
(source: string, chunk: webpack.Chunk) => {
if (compilation.chunkGraph === undefined) {
return source;
}
const ids: [string, string | number][] = [];
let hasDebugRequire = false;
compilation.chunkGraph.hasModuleInGraph(
chunk,
(m) => {
if (m instanceof webpack.NormalModule) {
const id = compilation.chunkGraph.getModuleId(m);
if (id === null) {
return false;
}
if (m.resource === debugRequirePath) {
hasDebugRequire = true;
}
const names = resolved.get(m.resource) ?? [];
for (const name of names) {
ids.push([
m.rawRequest.slice(0, m.rawRequest.lastIndexOf("!") + 1) +
name,
id,
]);
}
}
return false;
},
() => true,
);
if (!hasDebugRequire) {
return source;
}
ids.sort(([a], [b]) => Number(a > b) - Number(a < b));
return webpack.Template.asString([
source,
`__webpack_require__.debugRequireIds = ${JSON.stringify(
Object.fromEntries(ids),
null,
"\t",
)};`,
]);
},
);
});
}
}