-
-
Notifications
You must be signed in to change notification settings - Fork 9.5k
Expand file tree
/
Copy pathDependency.js
More file actions
538 lines (479 loc) · 17.2 KB
/
Copy pathDependency.js
File metadata and controls
538 lines (479 loc) · 17.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const memoize = require("./util/memoize");
/** @typedef {import("./ChunkGraph")} ChunkGraph */
/** @typedef {import("./DependenciesBlock")} DependenciesBlock */
/** @typedef {import("./Module")} Module */
/** @typedef {import("./ModuleGraph")} ModuleGraph */
/** @typedef {import("./ModuleGraphConnection")} ModuleGraphConnection */
/** @typedef {import("./ModuleGraphConnection").ConnectionState} ConnectionState */
/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
/** @typedef {import("./errors/WebpackError")} WebpackError */
/** @typedef {import("./serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
/** @typedef {import("./serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
/** @typedef {import("./util/Hash")} Hash */
/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
/** @typedef {import("./dependencies/ModuleDependency")} ModuleDependency */
/**
* Defines the update hash context type used by this module.
* @typedef {object} UpdateHashContext
* @property {ChunkGraph} chunkGraph
* @property {RuntimeSpec} runtime
* @property {RuntimeTemplate=} runtimeTemplate
*/
/**
* Defines the source position type used by this module.
* @typedef {object} SourcePosition
* @property {number} line
* @property {number=} column
*/
/**
* Defines the real dependency location type used by this module.
* @typedef {object} RealDependencyLocation
* @property {SourcePosition} start
* @property {SourcePosition=} end
* @property {number=} index
*/
/**
* Defines the synthetic dependency location type used by this module.
* @typedef {object} SyntheticDependencyLocation
* @property {string} name
* @property {number=} index
*/
/** @typedef {SyntheticDependencyLocation | RealDependencyLocation} DependencyLocation */
/** @typedef {string} ExportInfoName */
/**
* Defines the export spec type used by this module.
* @typedef {object} ExportSpec
* @property {ExportInfoName} name the name of the export
* @property {boolean=} canMangle can the export be renamed (defaults to true)
* @property {boolean=} terminalBinding is the export a terminal binding that should be checked for export star conflicts
* @property {boolean=} isPure calling this export has no observable side effects
* @property {(string | ExportSpec)[]=} exports nested exports
* @property {ModuleGraphConnection=} from when reexported: from which module
* @property {string[] | null=} export when reexported: from which export
* @property {number=} priority when reexported: with which priority
* @property {boolean=} hidden export is not visible, because another export blends over it
* @property {import("./optimize/InlineExports").InlinedValue=} inlined when set: the export binds to a small primitive constant eligible for inlining
*/
/** @typedef {Set<string>} ExportsSpecExcludeExports */
/**
* Defines the exports spec type used by this module.
* @typedef {object} ExportsSpec
* @property {(string | ExportSpec)[] | true | null} exports exported names, true for unknown exports or null for no exports
* @property {ExportsSpecExcludeExports=} excludeExports when exports = true, list of unaffected exports
* @property {(Set<string> | null)=} hideExports list of maybe prior exposed, but now hidden exports
* @property {ModuleGraphConnection=} from when reexported: from which module
* @property {number=} priority when reexported: with which priority
* @property {boolean=} canMangle can the export be renamed (defaults to true)
* @property {boolean=} terminalBinding are the exports terminal bindings that should be checked for export star conflicts
* @property {boolean=} isPure calling these exports has no observable side effects
* @property {Module[]=} dependencies module on which the result depends on
*/
/**
* Defines the referenced export type used by this module.
* @typedef {object} ReferencedExport
* @property {string[]} name name of the referenced export
* @property {boolean=} canMangle when false, referenced export can not be mangled, defaults to true
* @property {boolean=} canInline when false, the referenced export can not be substituted with an inlined literal at this site, defaults to true
*/
/** @typedef {string[][]} RawReferencedExports */
/** @typedef {(string[] | ReferencedExport)[]} ReferencedExports */
/** @typedef {(moduleGraphConnection: ModuleGraphConnection, runtime: RuntimeSpec) => ConnectionState} GetConditionFn */
/**
* Lazy barrel classification of a dependency within a side-effect-free module.
* `LAZY_UNTIL_LOCAL`: locally provided export name (`getLazyName`), requesting it requires no dependency.
* `LAZY_UNTIL_ID`: named re-export (`getLazyName`) deferred until the export name is requested.
* `LAZY_UNTIL_FALLBACK`: star re-export, deferred until an unknown name or all names are requested.
* `LAZY_UNTIL_REQUEST`: deferred together with other dependencies of the same request.
* @typedef {"local" | "id" | "*" | "@"} LazyUntil
*/
const LAZY_UNTIL_LOCAL = /** @type {"local"} */ ("local");
const LAZY_UNTIL_ID = /** @type {"id"} */ ("id");
const LAZY_UNTIL_FALLBACK = /** @type {"*"} */ ("*");
const LAZY_UNTIL_REQUEST = /** @type {"@"} */ ("@");
const TRANSITIVE = /** @type {symbol} */ (Symbol("transitive"));
const getIgnoredModule = memoize(() => {
const RawModule = require("./RawModule");
const module = new RawModule("/* (ignored) */", "ignored", "(ignored)");
module.factoryMeta = { sideEffectFree: true };
return module;
});
class Dependency {
constructor() {
/** @type {Module | undefined} */
this._parentModule = undefined;
/** @type {DependenciesBlock | undefined} */
this._parentDependenciesBlock = undefined;
/** @type {number} */
this._parentDependenciesBlockIndex = -1;
// stays on base: also set on ContextDependency, which is not a ModuleDependency
/** @type {boolean | undefined} */
this.optional = false;
/** @type {number} */
this._locSL = 0;
/** @type {number} */
this._locSC = 0;
/** @type {number} */
this._locEL = 0;
/** @type {number} */
this._locEC = 0;
/** @type {undefined | number} */
this._locI = undefined;
/** @type {undefined | string} */
this._locN = undefined;
/** @type {undefined | DependencyLocation} */
this._loc = undefined;
}
/**
* Returns a display name for the type of dependency.
* @returns {string} a display name for the type of dependency
*/
get type() {
return "unknown";
}
/**
* Returns a dependency category, typical categories are "commonjs", "amd", "esm".
* @returns {string} a dependency category, typical categories are "commonjs", "amd", "esm"
*/
get category() {
return "unknown";
}
/**
* Returns location.
* @returns {DependencyLocation} location
*/
get loc() {
if (this._loc !== undefined) return this._loc;
/** @type {SyntheticDependencyLocation & RealDependencyLocation} */
const loc = {};
if (this._locSL > 0) {
loc.start = { line: this._locSL, column: this._locSC };
}
if (this._locEL > 0) {
loc.end = { line: this._locEL, column: this._locEC };
}
if (this._locN !== undefined) {
loc.name = this._locN;
}
if (this._locI !== undefined) {
loc.index = this._locI;
}
return (this._loc = loc);
}
set loc(loc) {
if ("start" in loc && typeof loc.start === "object") {
this._locSL = loc.start.line || 0;
this._locSC = loc.start.column || 0;
} else {
this._locSL = 0;
this._locSC = 0;
}
if ("end" in loc && typeof loc.end === "object") {
this._locEL = loc.end.line || 0;
this._locEC = loc.end.column || 0;
} else {
this._locEL = 0;
this._locEC = 0;
}
this._locI = "index" in loc ? loc.index : undefined;
this._locN = "name" in loc ? loc.name : undefined;
// Don't retain the passed object; `get loc` rebuilds it from the numbers
// above on demand, so dependencies whose loc is never read hold 4 numbers
// instead of a SourceLocation + two Position objects.
this._loc = undefined;
}
/**
* Updates loc using the provided start line.
* @param {number} startLine start line
* @param {number} startColumn start column
* @param {number} endLine end line
* @param {number} endColumn end column
*/
setLoc(startLine, startColumn, endLine, endColumn) {
this._locSL = startLine;
this._locSC = startColumn;
this._locEL = endLine;
this._locEC = endColumn;
this._locI = undefined;
this._locN = undefined;
this._loc = undefined;
}
/**
* Updates loc from a source location plus an explicit index, without
* materializing the `loc` object (keeps `get loc` lazy). Replaces the
* `dep.loc = Object.create(loc); dep.loc.index = i` pattern, which both
* allocated a copy and stored the index outside the serialized fields.
* @param {DependencyLocation} loc source location (start/end/name read from it)
* @param {number} index dependency index within the statement
*/
setLocWithIndex(loc, index) {
this.loc = loc;
this._locI = index;
}
/**
* Compares two dependencies by source location for sorting a module's
* `dependencies`, without materializing the `loc` objects (`get loc` caches
* its result, so comparing through it would retain a location object on every
* sorted dependency). These dependencies always carry a real source position,
* so only start (line, column) and the within-statement index are compared; a
* dependency without an index sorts after one that has an index at the same
* position.
* @param {Dependency} a first dependency
* @param {Dependency} b second dependency
* @returns {-1 | 0 | 1} compare result
*/
static compareLocations(a, b) {
if (a._locSL !== b._locSL) return a._locSL < b._locSL ? -1 : 1;
if (a._locSC !== b._locSC) return a._locSC < b._locSC ? -1 : 1;
const ai = a._locI;
const bi = b._locI;
if (ai === bi) return 0;
if (ai === undefined) return 1;
if (bi === undefined) return -1;
return ai < bi ? -1 : 1;
}
/**
* Returns a request context.
* @returns {string | undefined} a request context
*/
getContext() {
return undefined;
}
/**
* Returns an identifier to merge equal requests.
* @returns {string | null} an identifier to merge equal requests
*/
getResourceIdentifier() {
return null;
}
/**
* Could affect referencing module.
* @returns {boolean | TRANSITIVE} true, when changes to the referenced module could affect the referencing module; TRANSITIVE, when changes to the referenced module could affect referencing modules of the referencing module
*/
couldAffectReferencingModule() {
return TRANSITIVE;
}
/**
* Returns the export name this dependency requests from its target module (lazy barrel optimization).
* @returns {string | true | null} export name, true for all exports, null for none
*/
getForwardId() {
// unknown dependency types conservatively request all exports
return true;
}
/**
* Returns how this dependency may be deferred when its parent module is side-effect-free (lazy barrel optimization).
* @returns {LazyUntil | null} lazy classification, null when it must be processed eagerly
*/
getLazyUntil() {
return null;
}
/**
* Returns the export name for a `LAZY_UNTIL_LOCAL`/`LAZY_UNTIL_ID` classification (lazy barrel optimization).
* @returns {string | null} export name, null when not applicable
*/
getLazyName() {
return null;
}
/**
* Whether the lazy barrel currently defers creating this dependency's target module (lazy barrel optimization).
* @returns {boolean} true while deferred, so it must not be processed or rendered
*/
isLazy() {
return false;
}
/**
* Sets whether the lazy barrel defers creating this dependency's target module (lazy barrel optimization).
* @param {boolean} value true to defer, false to create it now
*/
setLazy(value) {}
/**
* Returns the referenced module and export
* @deprecated
* @param {ModuleGraph} moduleGraph module graph
* @returns {never} throws error
*/
getReference(moduleGraph) {
throw new Error(
"Dependency.getReference was removed in favor of Dependency.getReferencedExports, ModuleGraph.getModule, ModuleGraph.getConnection(), and ModuleGraphConnection.getActiveState(runtime)"
);
}
/**
* Returns list of exports referenced by this dependency
* @param {ModuleGraph} moduleGraph module graph
* @param {RuntimeSpec} runtime the runtime for which the module is analysed
* @returns {ReferencedExports} referenced exports
*/
getReferencedExports(moduleGraph, runtime) {
return Dependency.EXPORTS_OBJECT_REFERENCED;
}
/**
* Returns function to determine if the connection is active.
* @param {ModuleGraph} moduleGraph module graph
* @returns {null | false | GetConditionFn} function to determine if the connection is active
*/
getCondition(moduleGraph) {
return null;
}
/**
* Returns the exported names
* @param {ModuleGraph} moduleGraph module graph
* @returns {ExportsSpec | undefined} export names
*/
getExports(moduleGraph) {
return undefined;
}
/**
* Returns warnings.
* @param {ModuleGraph} moduleGraph module graph
* @returns {WebpackError[] | null | undefined} warnings
*/
getWarnings(moduleGraph) {
return null;
}
/**
* Returns errors.
* @param {ModuleGraph} moduleGraph module graph
* @returns {WebpackError[] | null | undefined} errors
*/
getErrors(moduleGraph) {
return null;
}
/**
* Updates the hash with the data contributed by this instance.
* @param {Hash} hash hash to be updated
* @param {UpdateHashContext} context context
* @returns {void}
*/
updateHash(hash, context) {}
/**
* implement this method to allow the occurrence order plugin to count correctly
* @returns {number} count how often the id is used in this dependency
*/
getNumberOfIdOccurrences() {
return 1;
}
/**
* Gets module evaluation side effects state.
* @param {ModuleGraph} moduleGraph the module graph
* @returns {ConnectionState} how this dependency connects the module to referencing modules
*/
getModuleEvaluationSideEffectsState(moduleGraph) {
return true;
}
/**
* Creates an ignored module.
* @param {string} context context directory
* @returns {Module} ignored module
*/
createIgnoredModule(context) {
return getIgnoredModule();
}
/**
* Returns true if this dependency can be concatenated
* @returns {boolean} true if this dependency can be concatenated
*/
canConcatenate() {
return false;
}
/**
* Serializes this instance into the provided serializer context.
* @param {ObjectSerializerContext} context context
*/
serialize({ write }) {
write(this.optional);
write(this._locSL);
write(this._locSC);
write(this._locEL);
write(this._locEC);
write(this._locI);
write(this._locN);
}
/**
* Restores this instance from the provided deserializer context.
* @param {ObjectDeserializerContext} context context
*/
deserialize({ read }) {
this.optional = read();
this._locSL = read();
this._locSC = read();
this._locEL = read();
this._locEC = read();
this._locI = read();
this._locN = read();
}
}
/** @type {RawReferencedExports} */
Dependency.NO_EXPORTS_REFERENCED = [];
/** @type {RawReferencedExports} */
Dependency.EXPORTS_OBJECT_REFERENCED = [[]];
// Like EXPORTS_OBJECT_REFERENCED, but the reference can be rendered as a
// decoupled namespace object, so the module's exports stay mangleable.
// Same shape as EXPORTS_OBJECT_REFERENCED; only distinguished by identity.
/** @type {RawReferencedExports} */
Dependency.EXPORTS_OBJECT_REFERENCED_MANGLEABLE = [[]];
// TODO remove in webpack 6
Object.defineProperty(Dependency.prototype, "module", {
/**
* Returns throws.
* @deprecated
* @returns {EXPECTED_ANY} throws
*/
get() {
throw new Error(
"module property was removed from Dependency (use compilation.moduleGraph.getModule(dependency) instead)"
);
},
/**
* Updates module.
* @deprecated
* @returns {never} throws
*/
set() {
throw new Error(
"module property was removed from Dependency (use compilation.moduleGraph.updateModule(dependency, module) instead)"
);
}
});
/**
* Returns true if the dependency is a low priority dependency.
* @param {Dependency} dependency dep
* @returns {boolean} true if the dependency is a low priority dependency
*/
Dependency.isLowPriorityDependency = (dependency) =>
/** @type {ModuleDependency} */ (dependency).sourceOrder === Infinity;
// TODO in webpack 6, call canConcatenate() directly on the dependency instance instead of using this static method.
/**
* Returns true if the dependency can be concatenated (scope hoisting).
* @param {Dependency} dependency dep
* @returns {boolean} true if this dependency supports concatenation
*/
Dependency.canConcatenate = (dependency) => {
if (typeof dependency.canConcatenate === "function") {
return dependency.canConcatenate();
}
return false;
};
// TODO remove in webpack 6
Object.defineProperty(Dependency.prototype, "disconnect", {
/**
* Returns throws.
* @deprecated
* @returns {EXPECTED_ANY} throws
*/
get() {
throw new Error(
"disconnect was removed from Dependency (Dependency no longer carries graph specific information)"
);
}
});
Dependency.TRANSITIVE = TRANSITIVE;
Dependency.LAZY_UNTIL_LOCAL = LAZY_UNTIL_LOCAL;
Dependency.LAZY_UNTIL_ID = LAZY_UNTIL_ID;
Dependency.LAZY_UNTIL_FALLBACK = LAZY_UNTIL_FALLBACK;
Dependency.LAZY_UNTIL_REQUEST = LAZY_UNTIL_REQUEST;
module.exports = Dependency;