source: frontend/node_modules/webpack/lib/CompatibilityPlugin.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 8.2 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const {
9 JAVASCRIPT_MODULE_TYPE_AUTO,
10 JAVASCRIPT_MODULE_TYPE_DYNAMIC,
11 JAVASCRIPT_MODULE_TYPE_ESM
12} = require("./ModuleTypeConstants");
13const RuntimeGlobals = require("./RuntimeGlobals");
14const ConstDependency = require("./dependencies/ConstDependency");
15
16/** @typedef {import("estree").CallExpression} CallExpression */
17/** @typedef {import("./Compiler")} Compiler */
18/** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */
19/** @typedef {import("./dependencies/ContextDependency")} ContextDependency */
20/** @typedef {import("./javascript/JavascriptParser")} JavascriptParser */
21/** @typedef {import("./javascript/JavascriptParser").Range} Range */
22
23/**
24 * Captures the source range of a renamed compatibility binding so it can be
25 * rewritten exactly once.
26 * @typedef {object} CompatibilitySettingsDeclaration
27 * @property {boolean} updated
28 * @property {DependencyLocation} loc
29 * @property {Range} range
30 */
31
32/**
33 * Stores the replacement variable name and the declaration metadata tracked
34 * for a compatibility rewrite.
35 * @typedef {object} CompatibilitySettings
36 * @property {string} name
37 * @property {CompatibilitySettingsDeclaration} declaration
38 */
39
40const nestedWebpackIdentifierTag = Symbol("nested webpack identifier");
41const PLUGIN_NAME = "CompatibilityPlugin";
42
43/**
44 * Adds parser-time compatibility rewrites for legacy runtime patterns that
45 * webpack still needs to recognize in user and generated code.
46 */
47class CompatibilityPlugin {
48 /**
49 * Installs parser hooks that preserve compatibility with legacy patterns
50 * such as nested `__webpack_require__` bindings and hashbang handling.
51 * @param {Compiler} compiler the compiler instance
52 * @returns {void}
53 */
54 apply(compiler) {
55 compiler.hooks.compilation.tap(
56 PLUGIN_NAME,
57 (compilation, { normalModuleFactory }) => {
58 compilation.dependencyTemplates.set(
59 ConstDependency,
60 new ConstDependency.Template()
61 );
62
63 normalModuleFactory.hooks.parser
64 .for(JAVASCRIPT_MODULE_TYPE_AUTO)
65 .tap(PLUGIN_NAME, (parser, parserOptions) => {
66 if (
67 parserOptions.browserify !== undefined &&
68 !parserOptions.browserify
69 ) {
70 return;
71 }
72
73 parser.hooks.call.for("require").tap(
74 PLUGIN_NAME,
75 /**
76 * Rewrites browserify-style delegated `require` calls into a
77 * plain webpack require reference and removes the synthetic
78 * context dependency created for the delegator pattern.
79 * @param {CallExpression} expr call expression
80 * @returns {boolean | void} true when need to handle
81 */
82 (expr) => {
83 // support for browserify style require delegator: "require(o, !0)"
84 if (expr.arguments.length !== 2) return;
85 const second = parser.evaluateExpression(expr.arguments[1]);
86 if (!second.isBoolean()) return;
87 if (second.asBool() !== true) return;
88 const dep = new ConstDependency(
89 "require",
90 /** @type {Range} */ (expr.callee.range)
91 );
92 dep.loc = /** @type {DependencyLocation} */ (expr.loc);
93 if (parser.state.current.dependencies.length > 0) {
94 const last =
95 /** @type {ContextDependency} */
96 (
97 parser.state.current.dependencies[
98 parser.state.current.dependencies.length - 1
99 ]
100 );
101 if (
102 last.critical &&
103 last.options &&
104 last.options.request === "." &&
105 last.userRequest === "." &&
106 last.options.recursive
107 ) {
108 parser.state.current.dependencies.pop();
109 }
110 }
111 parser.state.module.addPresentationalDependency(dep);
112 return true;
113 }
114 );
115 });
116
117 /**
118 * Attaches the compatibility rewrites for a JavaScript parser
119 * instance.
120 * @param {JavascriptParser} parser the parser
121 * @returns {void}
122 */
123 const handler = (parser) => {
124 // Handle nested requires
125 parser.hooks.preStatement.tap(PLUGIN_NAME, (statement) => {
126 if (
127 statement.type === "FunctionDeclaration" &&
128 statement.id &&
129 statement.id.name === RuntimeGlobals.require
130 ) {
131 const newName = `__nested_webpack_require_${
132 /** @type {Range} */
133 (statement.range)[0]
134 }__`;
135 parser.tagVariable(
136 statement.id.name,
137 nestedWebpackIdentifierTag,
138 {
139 name: newName,
140 declaration: {
141 updated: false,
142 loc: /** @type {DependencyLocation} */ (statement.id.loc),
143 range: /** @type {Range} */ (statement.id.range)
144 }
145 }
146 );
147 return true;
148 }
149 });
150 parser.hooks.pattern
151 .for(RuntimeGlobals.require)
152 .tap(PLUGIN_NAME, (pattern) => {
153 const newName = `__nested_webpack_require_${
154 /** @type {Range} */ (pattern.range)[0]
155 }__`;
156 parser.tagVariable(pattern.name, nestedWebpackIdentifierTag, {
157 name: newName,
158 declaration: {
159 updated: false,
160 loc: /** @type {DependencyLocation} */ (pattern.loc),
161 range: /** @type {Range} */ (pattern.range)
162 }
163 });
164 if (parser.scope.topLevelScope !== true) {
165 return true;
166 }
167 });
168 parser.hooks.pattern
169 .for(RuntimeGlobals.exports)
170 .tap(PLUGIN_NAME, (pattern) => {
171 const newName = "__nested_webpack_exports__";
172 parser.tagVariable(pattern.name, nestedWebpackIdentifierTag, {
173 name: newName,
174 declaration: {
175 updated: false,
176 loc: /** @type {DependencyLocation} */ (pattern.loc),
177 range: /** @type {Range} */ (pattern.range)
178 }
179 });
180 return true;
181 });
182 // Update single `var __webpack_require__ = {};` and `var __webpack_exports__ = {};` without expression
183 parser.hooks.declarator.tap(PLUGIN_NAME, (declarator) => {
184 if (
185 declarator.id.type === "Identifier" &&
186 (declarator.id.name === RuntimeGlobals.exports ||
187 declarator.id.name === RuntimeGlobals.require)
188 ) {
189 const tagData = /** @type {CompatibilitySettings | undefined} */ (
190 parser.getTagData(
191 declarator.id.name,
192 nestedWebpackIdentifierTag
193 )
194 );
195 if (!tagData) return;
196 const { name, declaration } = tagData;
197 if (!declaration.updated) {
198 const dep = new ConstDependency(name, declaration.range);
199 dep.loc = declaration.loc;
200 parser.state.module.addPresentationalDependency(dep);
201 declaration.updated = true;
202 }
203 }
204 });
205 parser.hooks.expression
206 .for(nestedWebpackIdentifierTag)
207 .tap(PLUGIN_NAME, (expr) => {
208 const { name, declaration } =
209 /** @type {CompatibilitySettings} */
210 (parser.currentTagData);
211 if (!declaration.updated) {
212 const dep = new ConstDependency(name, declaration.range);
213 dep.loc = declaration.loc;
214 parser.state.module.addPresentationalDependency(dep);
215 declaration.updated = true;
216 }
217 const dep = new ConstDependency(
218 name,
219 /** @type {Range} */ (expr.range)
220 );
221 dep.loc = /** @type {DependencyLocation} */ (expr.loc);
222 parser.state.module.addPresentationalDependency(dep);
223 return true;
224 });
225
226 // Handle hashbang
227 parser.hooks.program.tap(PLUGIN_NAME, (program, comments) => {
228 if (comments.length === 0) return;
229 const c = comments[0];
230 if (c.type === "Line" && /** @type {Range} */ (c.range)[0] === 0) {
231 if (parser.state.source.slice(0, 2).toString() !== "#!") return;
232 // this is a hashbang comment
233 const dep = new ConstDependency("//", 0);
234 dep.loc = /** @type {DependencyLocation} */ (c.loc);
235 parser.state.module.addPresentationalDependency(dep);
236 }
237 });
238 };
239
240 normalModuleFactory.hooks.parser
241 .for(JAVASCRIPT_MODULE_TYPE_AUTO)
242 .tap(PLUGIN_NAME, handler);
243 normalModuleFactory.hooks.parser
244 .for(JAVASCRIPT_MODULE_TYPE_DYNAMIC)
245 .tap(PLUGIN_NAME, handler);
246 normalModuleFactory.hooks.parser
247 .for(JAVASCRIPT_MODULE_TYPE_ESM)
248 .tap(PLUGIN_NAME, handler);
249 }
250 );
251 }
252}
253
254module.exports = CompatibilityPlugin;
255module.exports.nestedWebpackIdentifierTag = nestedWebpackIdentifierTag;
Note: See TracBrowser for help on using the repository browser.