source: imaps-frontend/node_modules/webpack/lib/dependencies/URLPlugin.js@ 79a0317

main
Last change on this file since 79a0317 was 79a0317, checked in by stefan toskovski <stefantoska84@…>, 4 days ago

F4 Finalna Verzija

  • Property mode set to 100644
File size: 6.5 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Ivan Kopeykin @vankop
4*/
5
6"use strict";
7
8const { pathToFileURL } = require("url");
9const CommentCompilationWarning = require("../CommentCompilationWarning");
10const {
11 JAVASCRIPT_MODULE_TYPE_AUTO,
12 JAVASCRIPT_MODULE_TYPE_ESM
13} = require("../ModuleTypeConstants");
14const RuntimeGlobals = require("../RuntimeGlobals");
15const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning");
16const BasicEvaluatedExpression = require("../javascript/BasicEvaluatedExpression");
17const { approve } = require("../javascript/JavascriptParserHelpers");
18const InnerGraph = require("../optimize/InnerGraph");
19const ConstDependency = require("./ConstDependency");
20const URLDependency = require("./URLDependency");
21
22/** @typedef {import("estree").MemberExpression} MemberExpression */
23/** @typedef {import("estree").NewExpression} NewExpressionNode */
24/** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
25/** @typedef {import("../Compiler")} Compiler */
26/** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */
27/** @typedef {import("../NormalModule")} NormalModule */
28/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
29/** @typedef {import("../javascript/JavascriptParser")} Parser */
30/** @typedef {import("../javascript/JavascriptParser").Range} Range */
31
32const PLUGIN_NAME = "URLPlugin";
33
34class URLPlugin {
35 /**
36 * @param {Compiler} compiler compiler
37 */
38 apply(compiler) {
39 compiler.hooks.compilation.tap(
40 PLUGIN_NAME,
41 (compilation, { normalModuleFactory }) => {
42 compilation.dependencyFactories.set(URLDependency, normalModuleFactory);
43 compilation.dependencyTemplates.set(
44 URLDependency,
45 new URLDependency.Template()
46 );
47
48 /**
49 * @param {NormalModule} module module
50 * @returns {URL} file url
51 */
52 const getUrl = module => pathToFileURL(module.resource);
53
54 /**
55 * @param {Parser} parser parser parser
56 * @param {MemberExpression} arg arg
57 * @returns {boolean} true when it is `meta.url`, otherwise false
58 */
59 const isMetaUrl = (parser, arg) => {
60 const chain = parser.extractMemberExpressionChain(arg);
61
62 if (
63 chain.members.length !== 1 ||
64 chain.object.type !== "MetaProperty" ||
65 chain.object.meta.name !== "import" ||
66 chain.object.property.name !== "meta" ||
67 chain.members[0] !== "url"
68 )
69 return false;
70
71 return true;
72 };
73
74 /**
75 * @param {Parser} parser parser parser
76 * @param {JavascriptParserOptions} parserOptions parserOptions
77 * @returns {void}
78 */
79 const parserCallback = (parser, parserOptions) => {
80 if (parserOptions.url === false) return;
81 const relative = parserOptions.url === "relative";
82
83 /**
84 * @param {NewExpressionNode} expr expression
85 * @returns {undefined | string} request
86 */
87 const getUrlRequest = expr => {
88 if (expr.arguments.length !== 2) return;
89
90 const [arg1, arg2] = expr.arguments;
91
92 if (
93 arg2.type !== "MemberExpression" ||
94 arg1.type === "SpreadElement"
95 )
96 return;
97
98 if (!isMetaUrl(parser, arg2)) return;
99
100 return parser.evaluateExpression(arg1).asString();
101 };
102
103 parser.hooks.canRename.for("URL").tap(PLUGIN_NAME, approve);
104 parser.hooks.evaluateNewExpression
105 .for("URL")
106 .tap(PLUGIN_NAME, expr => {
107 const request = getUrlRequest(expr);
108 if (!request) return;
109 const url = new URL(request, getUrl(parser.state.module));
110
111 return new BasicEvaluatedExpression()
112 .setString(url.toString())
113 .setRange(/** @type {Range} */ (expr.range));
114 });
115 parser.hooks.new.for("URL").tap(PLUGIN_NAME, _expr => {
116 const expr = /** @type {NewExpressionNode} */ (_expr);
117 const { options: importOptions, errors: commentErrors } =
118 parser.parseCommentOptions(/** @type {Range} */ (expr.range));
119
120 if (commentErrors) {
121 for (const e of commentErrors) {
122 const { comment } = e;
123 parser.state.module.addWarning(
124 new CommentCompilationWarning(
125 `Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`,
126 /** @type {DependencyLocation} */ (comment.loc)
127 )
128 );
129 }
130 }
131
132 if (importOptions && importOptions.webpackIgnore !== undefined) {
133 if (typeof importOptions.webpackIgnore !== "boolean") {
134 parser.state.module.addWarning(
135 new UnsupportedFeatureWarning(
136 `\`webpackIgnore\` expected a boolean, but received: ${importOptions.webpackIgnore}.`,
137 /** @type {DependencyLocation} */ (expr.loc)
138 )
139 );
140 return;
141 } else if (importOptions.webpackIgnore) {
142 if (expr.arguments.length !== 2) return;
143
144 const [, arg2] = expr.arguments;
145
146 if (
147 arg2.type !== "MemberExpression" ||
148 !isMetaUrl(parser, arg2)
149 )
150 return;
151
152 const dep = new ConstDependency(
153 RuntimeGlobals.baseURI,
154 /** @type {Range} */ (arg2.range),
155 [RuntimeGlobals.baseURI]
156 );
157 dep.loc = /** @type {DependencyLocation} */ (expr.loc);
158 parser.state.module.addPresentationalDependency(dep);
159
160 return true;
161 }
162 }
163
164 const request = getUrlRequest(expr);
165
166 if (!request) return;
167
168 const [arg1, arg2] = expr.arguments;
169 const dep = new URLDependency(
170 request,
171 [
172 /** @type {Range} */ (arg1.range)[0],
173 /** @type {Range} */ (arg2.range)[1]
174 ],
175 /** @type {Range} */ (expr.range),
176 relative
177 );
178 dep.loc = /** @type {DependencyLocation} */ (expr.loc);
179 parser.state.current.addDependency(dep);
180 InnerGraph.onUsage(parser.state, e => (dep.usedByExports = e));
181 return true;
182 });
183 parser.hooks.isPure.for("NewExpression").tap(PLUGIN_NAME, _expr => {
184 const expr = /** @type {NewExpressionNode} */ (_expr);
185 const { callee } = expr;
186 if (callee.type !== "Identifier") return;
187 const calleeInfo = parser.getFreeInfoFromVariable(callee.name);
188 if (!calleeInfo || calleeInfo.name !== "URL") return;
189
190 const request = getUrlRequest(expr);
191
192 if (request) return true;
193 });
194 };
195
196 normalModuleFactory.hooks.parser
197 .for(JAVASCRIPT_MODULE_TYPE_AUTO)
198 .tap(PLUGIN_NAME, parserCallback);
199
200 normalModuleFactory.hooks.parser
201 .for(JAVASCRIPT_MODULE_TYPE_ESM)
202 .tap(PLUGIN_NAME, parserCallback);
203 }
204 );
205 }
206}
207
208module.exports = URLPlugin;
Note: See TracBrowser for help on using the repository browser.