Skip to content

Commit

Permalink
add createRequire support
Browse files Browse the repository at this point in the history
  • Loading branch information
vankop committed Mar 25, 2022
1 parent 86a8bd9 commit 34c4edc
Show file tree
Hide file tree
Showing 8 changed files with 395 additions and 73 deletions.
367 changes: 310 additions & 57 deletions lib/dependencies/CommonJsImportsParserPlugin.js

Large diffs are not rendered by default.

44 changes: 28 additions & 16 deletions lib/javascript/JavascriptParser.js
Expand Up @@ -165,6 +165,10 @@ class JavascriptParser extends Parser {
evaluateDefinedIdentifier: new HookMap(
() => new SyncBailHook(["expression"])
),
/** @type {HookMap<SyncBailHook<[CallExpressionNode], BasicEvaluatedExpression | undefined | null>>} */
evaluateCallExpression: new HookMap(
() => new SyncBailHook(["expression"])
),
/** @type {HookMap<SyncBailHook<[CallExpressionNode, BasicEvaluatedExpression | undefined], BasicEvaluatedExpression | undefined | null>>} */
evaluateCallExpressionMember: new HookMap(
() => new SyncBailHook(["expression", "param"])
Expand Down Expand Up @@ -1036,24 +1040,28 @@ class JavascriptParser extends Parser {
this.hooks.evaluate.for("CallExpression").tap("JavascriptParser", _expr => {
const expr = /** @type {CallExpressionNode} */ (_expr);
if (
expr.callee.type !== "MemberExpression" ||
expr.callee.property.type !==
expr.callee.type === "MemberExpression" &&
expr.callee.property.type ===
(expr.callee.computed ? "Literal" : "Identifier")
) {
return;
}

// type Super also possible here
const param = this.evaluateExpression(
/** @type {ExpressionNode} */ (expr.callee.object)
);
const property =
expr.callee.property.type === "Literal"
? `${expr.callee.property.value}`
: expr.callee.property.name;
const hook = this.hooks.evaluateCallExpressionMember.get(property);
if (hook !== undefined) {
return hook.call(expr, param);
// type Super also possible here
const param = this.evaluateExpression(
/** @type {ExpressionNode} */ (expr.callee.object)
);
const property =
expr.callee.property.type === "Literal"
? `${expr.callee.property.value}`
: expr.callee.property.name;
const hook = this.hooks.evaluateCallExpressionMember.get(property);
if (hook !== undefined) {
return hook.call(expr, param);
}
} else if (expr.callee.type === "Identifier") {
return this.callHooksForName(
this.hooks.evaluateCallExpression,
expr.callee.name,
expr
);
}
});
this.hooks.evaluateCallExpressionMember
Expand Down Expand Up @@ -3603,6 +3611,10 @@ class JavascriptParser extends Parser {
}
}

evaluatedVariable(tagInfo) {
return new VariableInfo(this.scope, undefined, tagInfo);
}

parseCommentOptions(range) {
const comments = this.getComments(range);
if (comments.length === 0) {
Expand Down
1 change: 1 addition & 0 deletions test/configCases/require/module-require/a.js
@@ -0,0 +1 @@
module.exports = 1;
1 change: 1 addition & 0 deletions test/configCases/require/module-require/b.js
@@ -0,0 +1 @@
module.exports = 2;
1 change: 1 addition & 0 deletions test/configCases/require/module-require/c.js
@@ -0,0 +1 @@
module.exports = 3;
40 changes: 40 additions & 0 deletions test/configCases/require/module-require/index.js
@@ -0,0 +1,40 @@
import { createRequire as _createRequire } from "module";
import { createRequire as __createRequire, builtinModules } from "module";

it("should evaluate require/createRequire", () => {
expect(
(function() { return typeof _createRequire; }).toString()
).toBe('function() { return "function"; }');
expect(
(function() { if (typeof _createRequire); }).toString()
).toBe('function() { if (true); }');
const require = __createRequire(import.meta.url);
expect(
(function() { return typeof require; }).toString()
).toBe('function() { return "function"; }');
expect(
(function() { if (typeof require); }).toString()
).toBe('function() { if (true); }');
});

it("should create require", () => {
const require = _createRequire(import.meta.url);
expect(require("./a")).toBe(1);
expect(_createRequire(import.meta.url)("./c")).toBe(3);
});

it("should resolve using created require", () => {
const require = _createRequire(import.meta.url);
expect(require.resolve("./b")).toBe("./b.js");
expect(_createRequire(import.meta.url).resolve("./b")).toBe("./b.js");
});

it("should provide require.cache", () => {
const _require = _createRequire(import.meta.url);
expect(require.cache).toBe(_require.cache);
expect(require.cache).toBe(_createRequire(import.meta.url).cache);
});

it("should import Node.js module", () => {
expect(Array.isArray(builtinModules)).toBe(true);
});
7 changes: 7 additions & 0 deletions test/configCases/require/module-require/webpack.config.js
@@ -0,0 +1,7 @@
/** @type {import("../../../../").Configuration} */
module.exports = {
target: "node",
optimization: {
moduleIds: "named"
}
};
7 changes: 7 additions & 0 deletions types.d.ts
Expand Up @@ -4884,6 +4884,12 @@ declare class JavascriptParser extends Parser {
undefined | null | BasicEvaluatedExpression
>
>;
evaluateCallExpression: HookMap<
SyncBailHook<
[CallExpression],
undefined | null | BasicEvaluatedExpression
>
>;
evaluateCallExpressionMember: HookMap<
SyncBailHook<
[CallExpression, undefined | BasicEvaluatedExpression],
Expand Down Expand Up @@ -5392,6 +5398,7 @@ declare class JavascriptParser extends Parser {
isVariableDefined(name?: any): boolean;
getVariableInfo(name: string): ExportedVariableInfo;
setVariable(name: string, variableInfo: ExportedVariableInfo): void;
evaluatedVariable(tagInfo?: any): VariableInfo;
parseCommentOptions(
range?: any
): { options: null; errors: null } | { options: object; errors: unknown[] };
Expand Down

0 comments on commit 34c4edc

Please sign in to comment.