UNPKG

5.83 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 RuntimeGlobals = require("./RuntimeGlobals");
9const WebpackError = require("./WebpackError");
10const ConstDependency = require("./dependencies/ConstDependency");
11const BasicEvaluatedExpression = require("./javascript/BasicEvaluatedExpression");
12const {
13 toConstantDependency,
14 evaluateToString
15} = require("./javascript/JavascriptParserHelpers");
16const ChunkNameRuntimeModule = require("./runtime/ChunkNameRuntimeModule");
17const GetFullHashRuntimeModule = require("./runtime/GetFullHashRuntimeModule");
18
19/** @typedef {import("./Compiler")} Compiler */
20/** @typedef {import("./javascript/JavascriptParser")} JavascriptParser */
21
22/* eslint-disable camelcase */
23const REPLACEMENTS = {
24 __webpack_require__: {
25 expr: RuntimeGlobals.require,
26 req: [RuntimeGlobals.require],
27 type: "function",
28 assign: false
29 },
30 __webpack_public_path__: {
31 expr: RuntimeGlobals.publicPath,
32 req: [RuntimeGlobals.publicPath],
33 type: "string",
34 assign: true
35 },
36 __webpack_base_uri__: {
37 expr: RuntimeGlobals.baseURI,
38 req: [RuntimeGlobals.baseURI],
39 type: "string",
40 assign: true
41 },
42 __webpack_modules__: {
43 expr: RuntimeGlobals.moduleFactories,
44 req: [RuntimeGlobals.moduleFactories],
45 type: "object",
46 assign: false
47 },
48 __webpack_chunk_load__: {
49 expr: RuntimeGlobals.ensureChunk,
50 req: [RuntimeGlobals.ensureChunk],
51 type: "function",
52 assign: true
53 },
54 __non_webpack_require__: {
55 expr: "require",
56 req: null,
57 type: undefined, // type is not known, depends on environment
58 assign: true
59 },
60 __webpack_nonce__: {
61 expr: RuntimeGlobals.scriptNonce,
62 req: [RuntimeGlobals.scriptNonce],
63 type: "string",
64 assign: true
65 },
66 __webpack_hash__: {
67 expr: `${RuntimeGlobals.getFullHash}()`,
68 req: [RuntimeGlobals.getFullHash],
69 type: "string",
70 assign: false
71 },
72 __webpack_chunkname__: {
73 expr: RuntimeGlobals.chunkName,
74 req: [RuntimeGlobals.chunkName],
75 type: "string",
76 assign: false
77 },
78 __webpack_get_script_filename__: {
79 expr: RuntimeGlobals.getChunkScriptFilename,
80 req: [RuntimeGlobals.getChunkScriptFilename],
81 type: "function",
82 assign: true
83 },
84 __webpack_runtime_id__: {
85 expr: RuntimeGlobals.runtimeId,
86 req: [RuntimeGlobals.runtimeId],
87 assign: false
88 },
89 "require.onError": {
90 expr: RuntimeGlobals.uncaughtErrorHandler,
91 req: [RuntimeGlobals.uncaughtErrorHandler],
92 type: undefined, // type is not known, could be function or undefined
93 assign: true // is never a pattern
94 },
95 __system_context__: {
96 expr: RuntimeGlobals.systemContext,
97 req: [RuntimeGlobals.systemContext],
98 type: "object",
99 assign: false
100 },
101 __webpack_share_scopes__: {
102 expr: RuntimeGlobals.shareScopeMap,
103 req: [RuntimeGlobals.shareScopeMap],
104 type: "object",
105 assign: false
106 },
107 __webpack_init_sharing__: {
108 expr: RuntimeGlobals.initializeSharing,
109 req: [RuntimeGlobals.initializeSharing],
110 type: "function",
111 assign: true
112 }
113};
114/* eslint-enable camelcase */
115
116class APIPlugin {
117 /**
118 * Apply the plugin
119 * @param {Compiler} compiler the compiler instance
120 * @returns {void}
121 */
122 apply(compiler) {
123 compiler.hooks.compilation.tap(
124 "APIPlugin",
125 (compilation, { normalModuleFactory }) => {
126 compilation.dependencyTemplates.set(
127 ConstDependency,
128 new ConstDependency.Template()
129 );
130
131 compilation.hooks.runtimeRequirementInTree
132 .for(RuntimeGlobals.chunkName)
133 .tap("APIPlugin", chunk => {
134 compilation.addRuntimeModule(
135 chunk,
136 new ChunkNameRuntimeModule(chunk.name)
137 );
138 return true;
139 });
140
141 compilation.hooks.runtimeRequirementInTree
142 .for(RuntimeGlobals.getFullHash)
143 .tap("APIPlugin", (chunk, set) => {
144 compilation.addRuntimeModule(chunk, new GetFullHashRuntimeModule());
145 return true;
146 });
147
148 /**
149 * @param {JavascriptParser} parser the parser
150 */
151 const handler = parser => {
152 Object.keys(REPLACEMENTS).forEach(key => {
153 const info = REPLACEMENTS[key];
154 parser.hooks.expression
155 .for(key)
156 .tap(
157 "APIPlugin",
158 toConstantDependency(parser, info.expr, info.req)
159 );
160 if (info.assign === false) {
161 parser.hooks.assign.for(key).tap("APIPlugin", expr => {
162 const err = new WebpackError(`${key} must not be assigned`);
163 err.loc = expr.loc;
164 throw err;
165 });
166 }
167 if (info.type) {
168 parser.hooks.evaluateTypeof
169 .for(key)
170 .tap("APIPlugin", evaluateToString(info.type));
171 }
172 });
173
174 parser.hooks.expression
175 .for("__webpack_layer__")
176 .tap("APIPlugin", expr => {
177 const dep = new ConstDependency(
178 JSON.stringify(parser.state.module.layer),
179 expr.range
180 );
181 dep.loc = expr.loc;
182 parser.state.module.addPresentationalDependency(dep);
183 return true;
184 });
185 parser.hooks.evaluateIdentifier
186 .for("__webpack_layer__")
187 .tap("APIPlugin", expr =>
188 (parser.state.module.layer === null
189 ? new BasicEvaluatedExpression().setNull()
190 : new BasicEvaluatedExpression().setString(
191 parser.state.module.layer
192 )
193 ).setRange(expr.range)
194 );
195 parser.hooks.evaluateTypeof
196 .for("__webpack_layer__")
197 .tap("APIPlugin", expr =>
198 new BasicEvaluatedExpression()
199 .setString(
200 parser.state.module.layer === null ? "object" : "string"
201 )
202 .setRange(expr.range)
203 );
204 };
205
206 normalModuleFactory.hooks.parser
207 .for("javascript/auto")
208 .tap("APIPlugin", handler);
209 normalModuleFactory.hooks.parser
210 .for("javascript/dynamic")
211 .tap("APIPlugin", handler);
212 normalModuleFactory.hooks.parser
213 .for("javascript/esm")
214 .tap("APIPlugin", handler);
215 }
216 );
217 }
218}
219
220module.exports = APIPlugin;