source: frontend/node_modules/webpack/lib/dependencies/HarmonyExportDependencyParserPlugin.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: 9.4 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 CompatibilityPlugin = require("../CompatibilityPlugin");
9const WebpackError = require("../errors/WebpackError");
10const { getImportAttributes } = require("../javascript/JavascriptParser");
11const InnerGraph = require("../optimize/InnerGraph");
12const ConstDependency = require("./ConstDependency");
13const HarmonyExportExpressionDependency = require("./HarmonyExportExpressionDependency");
14const HarmonyExportHeaderDependency = require("./HarmonyExportHeaderDependency");
15const HarmonyExportImportedSpecifierDependency = require("./HarmonyExportImportedSpecifierDependency");
16const HarmonyExportSpecifierDependency = require("./HarmonyExportSpecifierDependency");
17const { ExportPresenceModes } = require("./HarmonyImportDependency");
18const {
19 harmonySpecifierTag
20} = require("./HarmonyImportDependencyParserPlugin");
21const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDependency");
22const { ImportPhaseUtils, createGetImportPhase } = require("./ImportPhase");
23
24/** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
25/** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */
26/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
27/** @typedef {import("../javascript/JavascriptParser").ClassDeclaration} ClassDeclaration */
28/** @typedef {import("../javascript/JavascriptParser").FunctionDeclaration} FunctionDeclaration */
29/** @typedef {import("../javascript/JavascriptParser").Range} Range */
30/** @typedef {import("./HarmonyImportDependencyParserPlugin").HarmonySettings} HarmonySettings */
31/** @typedef {import("../CompatibilityPlugin").CompatibilitySettings} CompatibilitySettings */
32
33const { HarmonyStarExportsList } = HarmonyExportImportedSpecifierDependency;
34
35const PLUGIN_NAME = "HarmonyExportDependencyParserPlugin";
36
37module.exports = class HarmonyExportDependencyParserPlugin {
38 /**
39 * Creates an instance of HarmonyExportDependencyParserPlugin.
40 * @param {JavascriptParserOptions} options options
41 */
42 constructor(options) {
43 this.options = options;
44 this.exportPresenceMode = ExportPresenceModes.resolveFromOptions(
45 options.reexportExportsPresence,
46 options
47 );
48 }
49
50 /**
51 * Applies the plugin by registering its hooks on the compiler.
52 * @param {JavascriptParser} parser the parser
53 * @returns {void}
54 */
55 apply(parser) {
56 const { exportPresenceMode } = this;
57 const getImportPhase = createGetImportPhase(
58 this.options.deferImport,
59 false
60 );
61
62 parser.hooks.export.tap(PLUGIN_NAME, (statement) => {
63 const dep = new HarmonyExportHeaderDependency(
64 /** @type {Range | false} */ (
65 statement.declaration && statement.declaration.range
66 ),
67 /** @type {Range} */ (statement.range)
68 );
69 dep.loc = Object.create(
70 /** @type {DependencyLocation} */ (statement.loc)
71 );
72 dep.loc.index = -1;
73 parser.state.module.addPresentationalDependency(dep);
74 return true;
75 });
76 parser.hooks.exportImport.tap(PLUGIN_NAME, (statement, source) => {
77 parser.state.lastHarmonyImportOrder =
78 (parser.state.lastHarmonyImportOrder || 0) + 1;
79 const clearDep = new ConstDependency(
80 "",
81 /** @type {Range} */ (statement.range)
82 );
83 clearDep.loc = /** @type {DependencyLocation} */ (statement.loc);
84 clearDep.loc.index = -1;
85 parser.state.module.addPresentationalDependency(clearDep);
86
87 const phase = getImportPhase(parser, statement);
88 if (phase && ImportPhaseUtils.isDefer(phase)) {
89 const error = new WebpackError(
90 "Deferred re-export (`export defer * as namespace from '...'`) is not a part of the Import Defer proposal.\nUse the following code instead:\n import defer * as namespace from '...';\n export { namespace };"
91 );
92 error.loc = statement.loc || undefined;
93 parser.state.current.addError(error);
94 }
95 const sideEffectDep = new HarmonyImportSideEffectDependency(
96 /** @type {string} */ (source),
97 parser.state.lastHarmonyImportOrder,
98 phase,
99 getImportAttributes(statement)
100 );
101 sideEffectDep.loc = Object.create(
102 /** @type {DependencyLocation} */ (statement.loc)
103 );
104 sideEffectDep.loc.index = -1;
105 parser.state.current.addDependency(sideEffectDep);
106 return true;
107 });
108 parser.hooks.exportExpression.tap(PLUGIN_NAME, (statement, node) => {
109 const isFunctionDeclaration = node.type === "FunctionDeclaration";
110 const exprRange = /** @type {Range} */ (node.range);
111 const statementRange = /** @type {Range} */ (statement.range);
112 const comments = parser.getComments([statementRange[0], exprRange[0]]);
113 const dep = new HarmonyExportExpressionDependency(
114 exprRange,
115 statementRange,
116 comments
117 .map((c) => {
118 switch (c.type) {
119 case "Block":
120 return `/*${c.value}*/`;
121 case "Line":
122 return `//${c.value}\n`;
123 }
124 return "";
125 })
126 .join(""),
127 node.type.endsWith("Declaration") &&
128 /** @type {FunctionDeclaration | ClassDeclaration} */ (node).id
129 ? /** @type {FunctionDeclaration | ClassDeclaration} */
130 (node).id.name
131 : isFunctionDeclaration
132 ? {
133 range: [
134 exprRange[0],
135 node.params.length > 0
136 ? /** @type {Range} */ (node.params[0].range)[0]
137 : /** @type {Range} */ (node.body.range)[0]
138 ],
139 prefix: `${node.async ? "async " : ""}function${
140 node.generator ? "*" : ""
141 } `,
142 suffix: `(${node.params.length > 0 ? "" : ") "}`
143 }
144 : undefined
145 );
146 dep.isAnonymousDefault =
147 this.options.anonymousDefaultExportName !== false &&
148 (node.type === "ArrowFunctionExpression" ||
149 ((node.type === "FunctionDeclaration" ||
150 node.type === "FunctionExpression" ||
151 node.type === "ClassDeclaration" ||
152 node.type === "ClassExpression") &&
153 !node.id));
154 dep.loc = Object.create(
155 /** @type {DependencyLocation} */ (statement.loc)
156 );
157 dep.loc.index = -1;
158 parser.state.current.addDependency(dep);
159 InnerGraph.addVariableUsage(
160 parser,
161 node.type.endsWith("Declaration") &&
162 /** @type {FunctionDeclaration | ClassDeclaration} */ (node).id
163 ? /** @type {FunctionDeclaration | ClassDeclaration} */ (node).id.name
164 : "*default*",
165 "default"
166 );
167 return true;
168 });
169 parser.hooks.exportSpecifier.tap(
170 PLUGIN_NAME,
171 (statement, id, name, idx) => {
172 // CompatibilityPlugin may change exports name
173 // not handle re-export or import then export situation as current CompatibilityPlugin only
174 // rename symbol in declaration module, not change exported symbol
175 const variable = parser.getTagData(
176 id,
177 CompatibilityPlugin.nestedWebpackIdentifierTag
178 );
179 if (variable && /** @type {CompatibilitySettings} */ (variable).name) {
180 // CompatibilityPlugin changes exports to a new name, should updates exports name
181 id = /** @type {CompatibilitySettings} */ (variable).name;
182 }
183
184 const settings =
185 /** @type {HarmonySettings} */
186 (parser.getTagData(id, harmonySpecifierTag));
187 const harmonyNamedExports = (parser.state.harmonyNamedExports =
188 parser.state.harmonyNamedExports || new Set());
189 harmonyNamedExports.add(name);
190 InnerGraph.addVariableUsage(parser, id, name);
191 const dep = settings
192 ? new HarmonyExportImportedSpecifierDependency(
193 settings.source,
194 settings.sourceOrder,
195 settings.ids,
196 name,
197 harmonyNamedExports,
198 null,
199 exportPresenceMode,
200 null,
201 settings.phase,
202 settings.attributes
203 )
204 : new HarmonyExportSpecifierDependency(id, name);
205 dep.loc = Object.create(
206 /** @type {DependencyLocation} */ (statement.loc)
207 );
208 dep.loc.index = idx;
209 const isAsiSafe = !parser.isAsiPosition(
210 /** @type {Range} */
211 (statement.range)[0]
212 );
213 if (!isAsiSafe) {
214 parser.setAsiPosition(/** @type {Range} */ (statement.range)[1]);
215 }
216 parser.state.current.addDependency(dep);
217 return true;
218 }
219 );
220 parser.hooks.exportImportSpecifier.tap(
221 PLUGIN_NAME,
222 (statement, source, id, name, idx) => {
223 const harmonyNamedExports = (parser.state.harmonyNamedExports =
224 parser.state.harmonyNamedExports || new Set());
225 /** @type {InstanceType<HarmonyStarExportsList> | null} */
226 let harmonyStarExports = null;
227 if (name) {
228 harmonyNamedExports.add(name);
229 } else {
230 harmonyStarExports = parser.state.harmonyStarExports =
231 parser.state.harmonyStarExports || new HarmonyStarExportsList();
232 }
233 const attributes = getImportAttributes(statement);
234 const dep = new HarmonyExportImportedSpecifierDependency(
235 /** @type {string} */
236 (source),
237 /** @type {number} */
238 (parser.state.lastHarmonyImportOrder),
239 id ? [id] : [],
240 name,
241 harmonyNamedExports,
242 // eslint-disable-next-line unicorn/prefer-spread
243 harmonyStarExports && harmonyStarExports.slice(),
244 exportPresenceMode,
245 harmonyStarExports,
246 getImportPhase(parser, statement),
247 attributes
248 );
249 if (harmonyStarExports) {
250 harmonyStarExports.push(dep);
251 }
252 dep.loc = Object.create(
253 /** @type {DependencyLocation} */ (statement.loc)
254 );
255 dep.loc.index = idx;
256 const isAsiSafe = !parser.isAsiPosition(
257 /** @type {Range} */
258 (statement.range)[0]
259 );
260 if (!isAsiSafe) {
261 parser.setAsiPosition(/** @type {Range} */ (statement.range)[1]);
262 }
263 parser.state.current.addDependency(dep);
264 return true;
265 }
266 );
267 }
268};
Note: See TracBrowser for help on using the repository browser.