UNPKG

4.02 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const ConstDependency = require("./dependencies/ConstDependency");
9
10/** @typedef {import("./Compiler")} Compiler */
11/** @typedef {import("./javascript/JavascriptParser")} JavascriptParser */
12
13const nestedWebpackRequireTag = Symbol("nested __webpack_require__");
14
15class CompatibilityPlugin {
16 /**
17 * Apply the plugin
18 * @param {Compiler} compiler the compiler instance
19 * @returns {void}
20 */
21 apply(compiler) {
22 compiler.hooks.compilation.tap(
23 "CompatibilityPlugin",
24 (compilation, { normalModuleFactory }) => {
25 compilation.dependencyTemplates.set(
26 ConstDependency,
27 new ConstDependency.Template()
28 );
29
30 normalModuleFactory.hooks.parser
31 .for("javascript/auto")
32 .tap("CompatibilityPlugin", (parser, parserOptions) => {
33 if (
34 parserOptions.browserify !== undefined &&
35 !parserOptions.browserify
36 )
37 return;
38
39 parser.hooks.call
40 .for("require")
41 .tap("CompatibilityPlugin", expr => {
42 // support for browserify style require delegator: "require(o, !0)"
43 if (expr.arguments.length !== 2) return;
44 const second = parser.evaluateExpression(expr.arguments[1]);
45 if (!second.isBoolean()) return;
46 if (second.asBool() !== true) return;
47 const dep = new ConstDependency("require", expr.callee.range);
48 dep.loc = expr.loc;
49 if (parser.state.current.dependencies.length > 0) {
50 const last =
51 parser.state.current.dependencies[
52 parser.state.current.dependencies.length - 1
53 ];
54 if (
55 last.critical &&
56 last.options &&
57 last.options.request === "." &&
58 last.userRequest === "." &&
59 last.options.recursive
60 )
61 parser.state.current.dependencies.pop();
62 }
63 parser.state.module.addPresentationalDependency(dep);
64 return true;
65 });
66 });
67
68 /**
69 * @param {JavascriptParser} parser the parser
70 * @returns {void}
71 */
72 const nestedWebpackRequireHandler = parser => {
73 parser.hooks.preStatement.tap("CompatibilityPlugin", statement => {
74 if (
75 statement.type === "FunctionDeclaration" &&
76 statement.id &&
77 statement.id.name === "__webpack_require__"
78 ) {
79 const newName = `__nested_webpack_require_${statement.range[0]}__`;
80 const dep = new ConstDependency(newName, statement.id.range);
81 dep.loc = statement.id.loc;
82 parser.state.module.addPresentationalDependency(dep);
83 parser.tagVariable(
84 statement.id.name,
85 nestedWebpackRequireTag,
86 newName
87 );
88 return true;
89 }
90 });
91 parser.hooks.pattern
92 .for("__webpack_require__")
93 .tap("CompatibilityPlugin", pattern => {
94 const newName = `__nested_webpack_require_${pattern.range[0]}__`;
95 const dep = new ConstDependency(newName, pattern.range);
96 dep.loc = pattern.loc;
97 parser.state.module.addPresentationalDependency(dep);
98 parser.tagVariable(
99 pattern.name,
100 nestedWebpackRequireTag,
101 newName
102 );
103 return true;
104 });
105 parser.hooks.expression
106 .for(nestedWebpackRequireTag)
107 .tap("CompatibilityPlugin", expr => {
108 const newName = parser.currentTagData;
109 const dep = new ConstDependency(newName, expr.range);
110 dep.loc = expr.loc;
111 parser.state.module.addPresentationalDependency(dep);
112 return true;
113 });
114 };
115
116 normalModuleFactory.hooks.parser
117 .for("javascript/auto")
118 .tap("CompatibilityPlugin", nestedWebpackRequireHandler);
119 normalModuleFactory.hooks.parser
120 .for("javascript/dynamic")
121 .tap("CompatibilityPlugin", nestedWebpackRequireHandler);
122 normalModuleFactory.hooks.parser
123 .for("javascript/esm")
124 .tap("CompatibilityPlugin", nestedWebpackRequireHandler);
125 }
126 );
127 }
128}
129module.exports = CompatibilityPlugin;