1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | "use strict";
|
7 |
|
8 | const ConditionalInitFragment = require("../ConditionalInitFragment");
|
9 | const Dependency = require("../Dependency");
|
10 | const HarmonyLinkingError = require("../HarmonyLinkingError");
|
11 | const InitFragment = require("../InitFragment");
|
12 | const Template = require("../Template");
|
13 | const AwaitDependenciesInitFragment = require("../async-modules/AwaitDependenciesInitFragment");
|
14 | const { filterRuntime, mergeRuntime } = require("../util/runtime");
|
15 | const ModuleDependency = require("./ModuleDependency");
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 | const ExportPresenceModes = {
|
31 | NONE: (0),
|
32 | WARN: (1),
|
33 | AUTO: (2),
|
34 | ERROR: (3),
|
35 | fromUserOption(str) {
|
36 | switch (str) {
|
37 | case "error":
|
38 | return ExportPresenceModes.ERROR;
|
39 | case "warn":
|
40 | return ExportPresenceModes.WARN;
|
41 | case "auto":
|
42 | return ExportPresenceModes.AUTO;
|
43 | case false:
|
44 | return ExportPresenceModes.NONE;
|
45 | default:
|
46 | throw new Error(`Invalid export presence value ${str}`);
|
47 | }
|
48 | }
|
49 | };
|
50 |
|
51 | class HarmonyImportDependency extends ModuleDependency {
|
52 | |
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 | constructor(request, sourceOrder, assertions) {
|
59 | super(request);
|
60 | this.sourceOrder = sourceOrder;
|
61 | this.assertions = assertions;
|
62 | }
|
63 |
|
64 | get category() {
|
65 | return "esm";
|
66 | }
|
67 |
|
68 | |
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 | getReferencedExports(moduleGraph, runtime) {
|
75 | return Dependency.NO_EXPORTS_REFERENCED;
|
76 | }
|
77 |
|
78 | |
79 |
|
80 |
|
81 |
|
82 | getImportVar(moduleGraph) {
|
83 | const module = moduleGraph.getParentModule(this);
|
84 | const meta = moduleGraph.getMeta(module);
|
85 | let importVarMap = meta.importVarMap;
|
86 | if (!importVarMap) meta.importVarMap = importVarMap = new Map();
|
87 | let importVar = importVarMap.get(moduleGraph.getModule(this));
|
88 | if (importVar) return importVar;
|
89 | importVar = `${Template.toIdentifier(
|
90 | `${this.userRequest}`
|
91 | )}__WEBPACK_IMPORTED_MODULE_${importVarMap.size}__`;
|
92 | importVarMap.set(moduleGraph.getModule(this), importVar);
|
93 | return importVar;
|
94 | }
|
95 |
|
96 | |
97 |
|
98 |
|
99 |
|
100 |
|
101 | getImportStatement(
|
102 | update,
|
103 | { runtimeTemplate, module, moduleGraph, chunkGraph, runtimeRequirements }
|
104 | ) {
|
105 | return runtimeTemplate.importStatement({
|
106 | update,
|
107 | module: moduleGraph.getModule(this),
|
108 | chunkGraph,
|
109 | importVar: this.getImportVar(moduleGraph),
|
110 | request: this.request,
|
111 | originModule: module,
|
112 | runtimeRequirements
|
113 | });
|
114 | }
|
115 |
|
116 | |
117 |
|
118 |
|
119 |
|
120 |
|
121 |
|
122 | getLinkingErrors(moduleGraph, ids, additionalMessage) {
|
123 | const importedModule = moduleGraph.getModule(this);
|
124 |
|
125 | if (!importedModule || importedModule.getNumberOfErrors() > 0) {
|
126 | return;
|
127 | }
|
128 |
|
129 | const parentModule = moduleGraph.getParentModule(this);
|
130 | const exportsType = importedModule.getExportsType(
|
131 | moduleGraph,
|
132 | parentModule.buildMeta.strictHarmonyModule
|
133 | );
|
134 | if (exportsType === "namespace" || exportsType === "default-with-named") {
|
135 | if (ids.length === 0) {
|
136 | return;
|
137 | }
|
138 |
|
139 | if (
|
140 | (exportsType !== "default-with-named" || ids[0] !== "default") &&
|
141 | moduleGraph.isExportProvided(importedModule, ids) === false
|
142 | ) {
|
143 |
|
144 |
|
145 |
|
146 | let pos = 0;
|
147 | let exportsInfo = moduleGraph.getExportsInfo(importedModule);
|
148 | while (pos < ids.length && exportsInfo) {
|
149 | const id = ids[pos++];
|
150 | const exportInfo = exportsInfo.getReadOnlyExportInfo(id);
|
151 | if (exportInfo.provided === false) {
|
152 |
|
153 | const providedExports = exportsInfo.getProvidedExports();
|
154 | const moreInfo = !Array.isArray(providedExports)
|
155 | ? " (possible exports unknown)"
|
156 | : providedExports.length === 0
|
157 | ? " (module has no exports)"
|
158 | : ` (possible exports: ${providedExports.join(", ")})`;
|
159 | return [
|
160 | new HarmonyLinkingError(
|
161 | `export ${ids
|
162 | .slice(0, pos)
|
163 | .map(id => `'${id}'`)
|
164 | .join(".")} ${additionalMessage} was not found in '${
|
165 | this.userRequest
|
166 | }'${moreInfo}`
|
167 | )
|
168 | ];
|
169 | }
|
170 | exportsInfo = exportInfo.getNestedExportsInfo();
|
171 | }
|
172 |
|
173 |
|
174 | return [
|
175 | new HarmonyLinkingError(
|
176 | `export ${ids
|
177 | .map(id => `'${id}'`)
|
178 | .join(".")} ${additionalMessage} was not found in '${
|
179 | this.userRequest
|
180 | }'`
|
181 | )
|
182 | ];
|
183 | }
|
184 | }
|
185 | switch (exportsType) {
|
186 | case "default-only":
|
187 |
|
188 | if (ids.length > 0 && ids[0] !== "default") {
|
189 |
|
190 | return [
|
191 | new HarmonyLinkingError(
|
192 | `Can't import the named export ${ids
|
193 | .map(id => `'${id}'`)
|
194 | .join(
|
195 | "."
|
196 | )} ${additionalMessage} from default-exporting module (only default export is available)`
|
197 | )
|
198 | ];
|
199 | }
|
200 | break;
|
201 | case "default-with-named":
|
202 |
|
203 |
|
204 | if (
|
205 | ids.length > 0 &&
|
206 | ids[0] !== "default" &&
|
207 | importedModule.buildMeta.defaultObject === "redirect-warn"
|
208 | ) {
|
209 |
|
210 | return [
|
211 | new HarmonyLinkingError(
|
212 | `Should not import the named export ${ids
|
213 | .map(id => `'${id}'`)
|
214 | .join(
|
215 | "."
|
216 | )} ${additionalMessage} from default-exporting module (only default export is available soon)`
|
217 | )
|
218 | ];
|
219 | }
|
220 | break;
|
221 | }
|
222 | }
|
223 |
|
224 | serialize(context) {
|
225 | const { write } = context;
|
226 | write(this.sourceOrder);
|
227 | write(this.assertions);
|
228 | super.serialize(context);
|
229 | }
|
230 |
|
231 | deserialize(context) {
|
232 | const { read } = context;
|
233 | this.sourceOrder = read();
|
234 | this.assertions = read();
|
235 | super.deserialize(context);
|
236 | }
|
237 | }
|
238 |
|
239 | module.exports = HarmonyImportDependency;
|
240 |
|
241 |
|
242 | const importEmittedMap = new WeakMap();
|
243 |
|
244 | HarmonyImportDependency.Template = class HarmonyImportDependencyTemplate extends (
|
245 | ModuleDependency.Template
|
246 | ) {
|
247 | |
248 |
|
249 |
|
250 |
|
251 |
|
252 |
|
253 | apply(dependency, source, templateContext) {
|
254 | const dep = (dependency);
|
255 | const { module, chunkGraph, moduleGraph, runtime } = templateContext;
|
256 |
|
257 | const connection = moduleGraph.getConnection(dep);
|
258 | if (connection && !connection.isTargetActive(runtime)) return;
|
259 |
|
260 | const referencedModule = connection && connection.module;
|
261 |
|
262 | if (
|
263 | connection &&
|
264 | connection.weak &&
|
265 | referencedModule &&
|
266 | chunkGraph.getModuleId(referencedModule) === null
|
267 | ) {
|
268 |
|
269 |
|
270 | return;
|
271 | }
|
272 |
|
273 | const moduleKey = referencedModule
|
274 | ? referencedModule.identifier()
|
275 | : dep.request;
|
276 | const key = `harmony import ${moduleKey}`;
|
277 |
|
278 | const runtimeCondition = dep.weak
|
279 | ? false
|
280 | : connection
|
281 | ? filterRuntime(runtime, r => connection.isTargetActive(r))
|
282 | : true;
|
283 |
|
284 | if (module && referencedModule) {
|
285 | let emittedModules = importEmittedMap.get(module);
|
286 | if (emittedModules === undefined) {
|
287 | emittedModules = new WeakMap();
|
288 | importEmittedMap.set(module, emittedModules);
|
289 | }
|
290 | let mergedRuntimeCondition = runtimeCondition;
|
291 | const oldRuntimeCondition = emittedModules.get(referencedModule) || false;
|
292 | if (oldRuntimeCondition !== false && mergedRuntimeCondition !== true) {
|
293 | if (mergedRuntimeCondition === false || oldRuntimeCondition === true) {
|
294 | mergedRuntimeCondition = oldRuntimeCondition;
|
295 | } else {
|
296 | mergedRuntimeCondition = mergeRuntime(
|
297 | oldRuntimeCondition,
|
298 | mergedRuntimeCondition
|
299 | );
|
300 | }
|
301 | }
|
302 | emittedModules.set(referencedModule, mergedRuntimeCondition);
|
303 | }
|
304 |
|
305 | const importStatement = dep.getImportStatement(false, templateContext);
|
306 | if (
|
307 | referencedModule &&
|
308 | templateContext.moduleGraph.isAsync(referencedModule)
|
309 | ) {
|
310 | templateContext.initFragments.push(
|
311 | new ConditionalInitFragment(
|
312 | importStatement[0],
|
313 | InitFragment.STAGE_HARMONY_IMPORTS,
|
314 | dep.sourceOrder,
|
315 | key,
|
316 | runtimeCondition
|
317 | )
|
318 | );
|
319 | templateContext.initFragments.push(
|
320 | new AwaitDependenciesInitFragment(
|
321 | new Set([dep.getImportVar(templateContext.moduleGraph)])
|
322 | )
|
323 | );
|
324 | templateContext.initFragments.push(
|
325 | new ConditionalInitFragment(
|
326 | importStatement[1],
|
327 | InitFragment.STAGE_ASYNC_HARMONY_IMPORTS,
|
328 | dep.sourceOrder,
|
329 | key + " compat",
|
330 | runtimeCondition
|
331 | )
|
332 | );
|
333 | } else {
|
334 | templateContext.initFragments.push(
|
335 | new ConditionalInitFragment(
|
336 | importStatement[0] + importStatement[1],
|
337 | InitFragment.STAGE_HARMONY_IMPORTS,
|
338 | dep.sourceOrder,
|
339 | key,
|
340 | runtimeCondition
|
341 | )
|
342 | );
|
343 | }
|
344 | }
|
345 |
|
346 | |
347 |
|
348 |
|
349 |
|
350 |
|
351 |
|
352 | static getImportEmittedRuntime(module, referencedModule) {
|
353 | const emittedModules = importEmittedMap.get(module);
|
354 | if (emittedModules === undefined) return false;
|
355 | return emittedModules.get(referencedModule) || false;
|
356 | }
|
357 | };
|
358 |
|
359 | module.exports.ExportPresenceModes = ExportPresenceModes;
|