@wyw-in-js/transform 1.0.6 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/cache.js +100 -7
- package/esm/cache.js.map +1 -1
- package/esm/debug/fileReporter.js.map +1 -1
- package/esm/module.js +51 -2
- package/esm/module.js.map +1 -1
- package/esm/plugins/shaker.js +152 -13
- package/esm/plugins/shaker.js.map +1 -1
- package/esm/shaker.js +51 -23
- package/esm/shaker.js.map +1 -1
- package/esm/transform/BaseEntrypoint.js +3 -1
- package/esm/transform/BaseEntrypoint.js.map +1 -1
- package/esm/transform/Entrypoint.js +60 -17
- package/esm/transform/Entrypoint.js.map +1 -1
- package/esm/transform/EvaluatedEntrypoint.js.map +1 -1
- package/esm/transform/barrelManifest.js +291 -0
- package/esm/transform/barrelManifest.js.map +1 -0
- package/esm/transform/generators/getExports.js +5 -0
- package/esm/transform/generators/getExports.js.map +1 -1
- package/esm/transform/generators/processEntrypoint.js +27 -1
- package/esm/transform/generators/processEntrypoint.js.map +1 -1
- package/esm/transform/generators/resolveImports.js +29 -5
- package/esm/transform/generators/resolveImports.js.map +1 -1
- package/esm/transform/generators/rewriteBarrelImports.js +733 -0
- package/esm/transform/generators/rewriteBarrelImports.js.map +1 -0
- package/esm/transform/generators/transform.js +154 -21
- package/esm/transform/generators/transform.js.map +1 -1
- package/esm/transform/types.js.map +1 -1
- package/lib/cache.js +103 -7
- package/lib/cache.js.map +1 -1
- package/lib/debug/fileReporter.js.map +1 -1
- package/lib/module.js +51 -2
- package/lib/module.js.map +1 -1
- package/lib/plugins/shaker.js +152 -13
- package/lib/plugins/shaker.js.map +1 -1
- package/lib/shaker.js +58 -26
- package/lib/shaker.js.map +1 -1
- package/lib/transform/BaseEntrypoint.js +3 -1
- package/lib/transform/BaseEntrypoint.js.map +1 -1
- package/lib/transform/Entrypoint.js +61 -17
- package/lib/transform/Entrypoint.js.map +1 -1
- package/lib/transform/EvaluatedEntrypoint.js.map +1 -1
- package/lib/transform/barrelManifest.js +300 -0
- package/lib/transform/barrelManifest.js.map +1 -0
- package/lib/transform/generators/getExports.js +5 -0
- package/lib/transform/generators/getExports.js.map +1 -1
- package/lib/transform/generators/processEntrypoint.js +27 -1
- package/lib/transform/generators/processEntrypoint.js.map +1 -1
- package/lib/transform/generators/resolveImports.js +29 -5
- package/lib/transform/generators/resolveImports.js.map +1 -1
- package/lib/transform/generators/rewriteBarrelImports.js +743 -0
- package/lib/transform/generators/rewriteBarrelImports.js.map +1 -0
- package/lib/transform/generators/transform.js +158 -22
- package/lib/transform/generators/transform.js.map +1 -1
- package/lib/transform/types.js.map +1 -1
- package/package.json +8 -4
- package/types/cache.d.ts +16 -2
- package/types/cache.js +111 -7
- package/types/debug/fileReporter.d.ts +1 -0
- package/types/module.d.ts +3 -0
- package/types/module.js +57 -2
- package/types/plugins/shaker.js +161 -16
- package/types/shaker.d.ts +10 -1
- package/types/shaker.js +56 -28
- package/types/transform/BaseEntrypoint.d.ts +3 -1
- package/types/transform/BaseEntrypoint.js +5 -1
- package/types/transform/Entrypoint.d.ts +9 -0
- package/types/transform/Entrypoint.js +73 -20
- package/types/transform/EvaluatedEntrypoint.d.ts +2 -0
- package/types/transform/barrelManifest.d.ts +42 -0
- package/types/transform/barrelManifest.js +300 -0
- package/types/transform/generators/getExports.js +5 -0
- package/types/transform/generators/processEntrypoint.js +26 -1
- package/types/transform/generators/resolveImports.js +29 -5
- package/types/transform/generators/rewriteBarrelImports.d.ts +15 -0
- package/types/transform/generators/rewriteBarrelImports.js +815 -0
- package/types/transform/generators/transform.js +148 -19
- package/types/transform/types.d.ts +2 -0
|
@@ -12,11 +12,13 @@ export declare abstract class BaseEntrypoint {
|
|
|
12
12
|
readonly only: string[];
|
|
13
13
|
readonly parents: ParentEntrypoint[];
|
|
14
14
|
readonly dependencies: Map<string, IEntrypointDependency>;
|
|
15
|
+
readonly invalidationDependencies: Map<string, IEntrypointDependency>;
|
|
16
|
+
readonly invalidateOnDependencyChange: Set<string>;
|
|
15
17
|
static createExports: (log: Debugger) => Record<string | symbol, unknown>;
|
|
16
18
|
readonly idx: string;
|
|
17
19
|
readonly log: Debugger;
|
|
18
20
|
readonly seqId: number;
|
|
19
|
-
protected constructor(services: Services, evaluatedOnly: string[], exports: Record<string | symbol, unknown> | undefined, generation: number, name: string, only: string[], parents: ParentEntrypoint[], dependencies: Map<string, IEntrypointDependency>);
|
|
21
|
+
protected constructor(services: Services, evaluatedOnly: string[], exports: Record<string | symbol, unknown> | undefined, generation: number, name: string, only: string[], parents: ParentEntrypoint[], dependencies: Map<string, IEntrypointDependency>, invalidationDependencies: Map<string, IEntrypointDependency>, invalidateOnDependencyChange: Set<string>);
|
|
20
22
|
get exports(): Record<string | symbol, unknown>;
|
|
21
23
|
set exports(value: unknown);
|
|
22
24
|
get ref(): string;
|
|
@@ -116,13 +116,15 @@ class BaseEntrypoint {
|
|
|
116
116
|
only;
|
|
117
117
|
parents;
|
|
118
118
|
dependencies;
|
|
119
|
+
invalidationDependencies;
|
|
120
|
+
invalidateOnDependencyChange;
|
|
119
121
|
static createExports = exports.createExports;
|
|
120
122
|
idx;
|
|
121
123
|
log;
|
|
122
124
|
// eslint-disable-next-line no-plusplus
|
|
123
125
|
seqId = entrypointSeqId++;
|
|
124
126
|
#exports;
|
|
125
|
-
constructor(services, evaluatedOnly, exports, generation, name, only, parents, dependencies) {
|
|
127
|
+
constructor(services, evaluatedOnly, exports, generation, name, only, parents, dependencies, invalidationDependencies, invalidateOnDependencyChange) {
|
|
126
128
|
this.services = services;
|
|
127
129
|
this.evaluatedOnly = evaluatedOnly;
|
|
128
130
|
this.generation = generation;
|
|
@@ -130,6 +132,8 @@ class BaseEntrypoint {
|
|
|
130
132
|
this.only = only;
|
|
131
133
|
this.parents = parents;
|
|
132
134
|
this.dependencies = dependencies;
|
|
135
|
+
this.invalidationDependencies = invalidationDependencies;
|
|
136
|
+
this.invalidateOnDependencyChange = invalidateOnDependencyChange;
|
|
133
137
|
this.idx = (0, getFileIdx_1.getFileIdx)(name);
|
|
134
138
|
this.log =
|
|
135
139
|
parents[0]?.log.extend(this.ref, '->') ?? services.log.extend(this.ref);
|
|
@@ -10,6 +10,8 @@ export declare class Entrypoint extends BaseEntrypoint {
|
|
|
10
10
|
readonly initialCode: string | undefined;
|
|
11
11
|
protected readonly resolveTasks: Map<string, Promise<IEntrypointDependency>>;
|
|
12
12
|
readonly dependencies: Map<string, IEntrypointDependency>;
|
|
13
|
+
readonly invalidationDependencies: Map<string, IEntrypointDependency>;
|
|
14
|
+
readonly invalidateOnDependencyChange: Set<string>;
|
|
13
15
|
readonly evaluated = false;
|
|
14
16
|
readonly loadedAndParsed: IEntrypointCode | IIgnoredEntrypoint;
|
|
15
17
|
protected onSupersedeHandlers: Array<(newEntrypoint: Entrypoint) => void>;
|
|
@@ -35,16 +37,23 @@ export declare class Entrypoint extends BaseEntrypoint {
|
|
|
35
37
|
protected static create(services: Services, parent: ParentEntrypoint | null, name: string, only: string[], loadedCode: string | undefined): Entrypoint | 'loop';
|
|
36
38
|
private static innerCreate;
|
|
37
39
|
addDependency(dependency: IEntrypointDependency): void;
|
|
40
|
+
addInvalidationDependency(dependency: IEntrypointDependency): void;
|
|
38
41
|
addResolveTask(name: string, dependency: Promise<IEntrypointDependency>): void;
|
|
42
|
+
applyDeferredSupersede(): Entrypoint | null;
|
|
39
43
|
assertNotSuperseded(): void;
|
|
40
44
|
assertTransformed(): void;
|
|
45
|
+
beginProcessing(): void;
|
|
41
46
|
createAction<TType extends ActionTypes, TAction extends ActionByType<TType>>(actionType: TType, data: TAction['data'], abortSignal?: AbortSignal | null): BaseAction<TAction>;
|
|
42
47
|
createChild(name: string, only: string[], loadedCode?: string): Entrypoint | 'loop';
|
|
43
48
|
createEvaluated(): EvaluatedEntrypoint;
|
|
49
|
+
endProcessing(): void;
|
|
44
50
|
getDependency(name: string): IEntrypointDependency | undefined;
|
|
51
|
+
getInvalidationDependency(name: string): IEntrypointDependency | undefined;
|
|
52
|
+
markInvalidateOnDependencyChange(filename: string): void;
|
|
45
53
|
getResolveTask(name: string): Promise<IEntrypointDependency> | undefined;
|
|
46
54
|
hasWywMetadata(): boolean;
|
|
47
55
|
onSupersede(callback: (newEntrypoint: Entrypoint) => void): () => void;
|
|
48
56
|
setTransformResult(res: ITransformFileResult | null): void;
|
|
57
|
+
private deferOnlySupersede;
|
|
49
58
|
private supersede;
|
|
50
59
|
}
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.Entrypoint = void 0;
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
4
8
|
const ts_invariant_1 = require("ts-invariant");
|
|
5
9
|
const BaseEntrypoint_1 = require("./BaseEntrypoint");
|
|
6
10
|
const Entrypoint_helpers_1 = require("./Entrypoint.helpers");
|
|
7
|
-
const isStaticallyEvaluatableModule_1 = require("./isStaticallyEvaluatableModule");
|
|
8
11
|
const EvaluatedEntrypoint_1 = require("./EvaluatedEntrypoint");
|
|
9
12
|
const AbortError_1 = require("./actions/AbortError");
|
|
10
13
|
const BaseAction_1 = require("./actions/BaseAction");
|
|
11
14
|
const UnprocessedEntrypointError_1 = require("./actions/UnprocessedEntrypointError");
|
|
15
|
+
const parseRequest_1 = require("../utils/parseRequest");
|
|
12
16
|
const EMPTY_FILE = '=== empty file ===';
|
|
13
17
|
function hasLoop(name, parent, processed = []) {
|
|
14
18
|
if (parent.name === name || processed.includes(parent.name)) {
|
|
@@ -26,18 +30,24 @@ class Entrypoint extends BaseEntrypoint_1.BaseEntrypoint {
|
|
|
26
30
|
initialCode;
|
|
27
31
|
resolveTasks;
|
|
28
32
|
dependencies;
|
|
33
|
+
invalidationDependencies;
|
|
34
|
+
invalidateOnDependencyChange;
|
|
29
35
|
evaluated = false;
|
|
30
36
|
loadedAndParsed;
|
|
31
37
|
onSupersedeHandlers = [];
|
|
32
38
|
actionsCache = new Map();
|
|
33
39
|
#hasWywMetadata = false;
|
|
40
|
+
#isProcessing = false;
|
|
41
|
+
#pendingOnly = null;
|
|
34
42
|
#supersededWith = null;
|
|
35
43
|
#transformResultCode = null;
|
|
36
|
-
constructor(services, parents, initialCode, name, only, exports, evaluatedOnly, loadedAndParsed, resolveTasks = new Map(), dependencies = new Map(), generation = 1) {
|
|
37
|
-
super(services, evaluatedOnly, exports, generation, name, only, parents, dependencies);
|
|
44
|
+
constructor(services, parents, initialCode, name, only, exports, evaluatedOnly, loadedAndParsed, resolveTasks = new Map(), dependencies = new Map(), invalidationDependencies = new Map(), invalidateOnDependencyChange = new Set(), generation = 1) {
|
|
45
|
+
super(services, evaluatedOnly, exports, generation, name, only, parents, dependencies, invalidationDependencies, invalidateOnDependencyChange);
|
|
38
46
|
this.initialCode = initialCode;
|
|
39
47
|
this.resolveTasks = resolveTasks;
|
|
40
48
|
this.dependencies = dependencies;
|
|
49
|
+
this.invalidationDependencies = invalidationDependencies;
|
|
50
|
+
this.invalidateOnDependencyChange = invalidateOnDependencyChange;
|
|
41
51
|
this.loadedAndParsed =
|
|
42
52
|
loadedAndParsed ??
|
|
43
53
|
services.loadAndParseFn(services, name, initialCode, parents[0]?.log ?? services.log);
|
|
@@ -99,9 +109,18 @@ class Entrypoint extends BaseEntrypoint_1.BaseEntrypoint {
|
|
|
99
109
|
static innerCreate(services, parent, name, only, loadedCode) {
|
|
100
110
|
const { cache } = services;
|
|
101
111
|
const cached = cache.get('entrypoints', name);
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
112
|
+
let changed = false;
|
|
113
|
+
if (loadedCode !== undefined) {
|
|
114
|
+
changed = cache.invalidateIfChanged(name, loadedCode, undefined, 'loaded');
|
|
115
|
+
}
|
|
116
|
+
else if (cached && cached.initialCode === undefined) {
|
|
117
|
+
try {
|
|
118
|
+
changed = cache.invalidateIfChanged(name, node_fs_1.default.readFileSync((0, parseRequest_1.stripQueryAndHash)(name), 'utf8'), undefined, 'fs');
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
changed = false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
105
124
|
if (!cached?.evaluated && cached?.ignored) {
|
|
106
125
|
return ['cached', cached];
|
|
107
126
|
}
|
|
@@ -124,20 +143,18 @@ class Entrypoint extends BaseEntrypoint_1.BaseEntrypoint {
|
|
|
124
143
|
return [isLoop ? 'loop' : 'cached', cached];
|
|
125
144
|
}
|
|
126
145
|
cached.log('is cached, but with different `only` %o (the cached one %o)', only, cached?.only);
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
!newEntrypoint.only.includes('*') &&
|
|
132
|
-
!newEntrypoint.only.includes('__wywPreval') &&
|
|
133
|
-
!newEntrypoint.only.includes('side-effect')) {
|
|
134
|
-
const { ast } = newEntrypoint.loadedAndParsed;
|
|
135
|
-
if (ast && (0, isStaticallyEvaluatableModule_1.isStaticallyEvaluatableModule)(ast)) {
|
|
136
|
-
newEntrypoint.log('[entrypoint] promote `only` to "*" for statically evaluatable module');
|
|
137
|
-
newEntrypoint.only.length = 0;
|
|
138
|
-
newEntrypoint.only.push('*');
|
|
146
|
+
if (cached.#isProcessing) {
|
|
147
|
+
cached.deferOnlySupersede(mergedOnly);
|
|
148
|
+
cached.log('is being processed, defer supersede (%o -> %o)', cached.only, mergedOnly);
|
|
149
|
+
return [isLoop ? 'loop' : 'cached', cached];
|
|
139
150
|
}
|
|
151
|
+
return [isLoop ? 'loop' : 'created', cached.supersede(mergedOnly)];
|
|
140
152
|
}
|
|
153
|
+
const newEntrypoint = new Entrypoint(services, parent ? [parent] : [], loadedCode, name, mergedOnly, exports, evaluatedOnly, undefined, cached && 'resolveTasks' in cached ? cached.resolveTasks : undefined, cached && 'dependencies' in cached ? cached.dependencies : undefined, cached && 'invalidationDependencies' in cached
|
|
154
|
+
? cached.invalidationDependencies
|
|
155
|
+
: undefined, cached && 'invalidateOnDependencyChange' in cached
|
|
156
|
+
? cached.invalidateOnDependencyChange
|
|
157
|
+
: undefined, cached ? cached.generation + 1 : 1);
|
|
141
158
|
if (cached && !cached.evaluated) {
|
|
142
159
|
cached.log('is cached, but with different code');
|
|
143
160
|
cached.supersede(newEntrypoint);
|
|
@@ -148,9 +165,27 @@ class Entrypoint extends BaseEntrypoint_1.BaseEntrypoint {
|
|
|
148
165
|
this.resolveTasks.delete(dependency.source);
|
|
149
166
|
this.dependencies.set(dependency.source, dependency);
|
|
150
167
|
}
|
|
168
|
+
addInvalidationDependency(dependency) {
|
|
169
|
+
this.resolveTasks.delete(dependency.source);
|
|
170
|
+
this.invalidationDependencies.set(dependency.source, dependency);
|
|
171
|
+
}
|
|
151
172
|
addResolveTask(name, dependency) {
|
|
152
173
|
this.resolveTasks.set(name, dependency);
|
|
153
174
|
}
|
|
175
|
+
applyDeferredSupersede() {
|
|
176
|
+
if (this.#supersededWith || this.#pendingOnly === null) {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
const mergedOnly = (0, Entrypoint_helpers_1.mergeOnly)(this.only, this.#pendingOnly);
|
|
180
|
+
this.#pendingOnly = null;
|
|
181
|
+
if ((0, Entrypoint_helpers_1.isSuperSet)(this.only, mergedOnly)) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
this.log('apply deferred supersede (%o -> %o)', this.only, mergedOnly);
|
|
185
|
+
const nextEntrypoint = this.supersede(mergedOnly);
|
|
186
|
+
this.services.cache.add('entrypoints', this.name, nextEntrypoint);
|
|
187
|
+
return nextEntrypoint;
|
|
188
|
+
}
|
|
154
189
|
assertNotSuperseded() {
|
|
155
190
|
if (this.supersededWith) {
|
|
156
191
|
this.log('superseded');
|
|
@@ -163,6 +198,9 @@ class Entrypoint extends BaseEntrypoint_1.BaseEntrypoint {
|
|
|
163
198
|
throw new UnprocessedEntrypointError_1.UnprocessedEntrypointError(this.supersededWith ?? this);
|
|
164
199
|
}
|
|
165
200
|
}
|
|
201
|
+
beginProcessing() {
|
|
202
|
+
this.#isProcessing = true;
|
|
203
|
+
}
|
|
166
204
|
createAction(actionType, data, abortSignal = null) {
|
|
167
205
|
if (!this.actionsCache.has(actionType)) {
|
|
168
206
|
this.actionsCache.set(actionType, new Map());
|
|
@@ -187,13 +225,22 @@ class Entrypoint extends BaseEntrypoint_1.BaseEntrypoint {
|
|
|
187
225
|
createEvaluated() {
|
|
188
226
|
const evaluatedOnly = (0, Entrypoint_helpers_1.mergeOnly)(this.evaluatedOnly, this.only);
|
|
189
227
|
this.log('create EvaluatedEntrypoint for %o', evaluatedOnly);
|
|
190
|
-
const evaluated = new EvaluatedEntrypoint_1.EvaluatedEntrypoint(this.services, evaluatedOnly, this.exportsProxy, this.generation + 1, this.name, this.only, this.parents, this.dependencies);
|
|
228
|
+
const evaluated = new EvaluatedEntrypoint_1.EvaluatedEntrypoint(this.services, evaluatedOnly, this.exportsProxy, this.generation + 1, this.name, this.only, this.parents, this.dependencies, this.invalidationDependencies, this.invalidateOnDependencyChange);
|
|
191
229
|
evaluated.initialCode = this.initialCode;
|
|
192
230
|
return evaluated;
|
|
193
231
|
}
|
|
232
|
+
endProcessing() {
|
|
233
|
+
this.#isProcessing = false;
|
|
234
|
+
}
|
|
194
235
|
getDependency(name) {
|
|
195
236
|
return this.dependencies.get(name);
|
|
196
237
|
}
|
|
238
|
+
getInvalidationDependency(name) {
|
|
239
|
+
return this.invalidationDependencies.get(name);
|
|
240
|
+
}
|
|
241
|
+
markInvalidateOnDependencyChange(filename) {
|
|
242
|
+
this.invalidateOnDependencyChange.add(filename);
|
|
243
|
+
}
|
|
197
244
|
getResolveTask(name) {
|
|
198
245
|
return this.resolveTasks.get(name);
|
|
199
246
|
}
|
|
@@ -221,10 +268,16 @@ class Entrypoint extends BaseEntrypoint_1.BaseEntrypoint {
|
|
|
221
268
|
type: 'setTransformResult',
|
|
222
269
|
});
|
|
223
270
|
}
|
|
271
|
+
deferOnlySupersede(only) {
|
|
272
|
+
this.#pendingOnly = this.#pendingOnly
|
|
273
|
+
? (0, Entrypoint_helpers_1.mergeOnly)(this.#pendingOnly, only)
|
|
274
|
+
: [...only];
|
|
275
|
+
}
|
|
224
276
|
supersede(newOnlyOrEntrypoint) {
|
|
277
|
+
this.#pendingOnly = null;
|
|
225
278
|
const newEntrypoint = newOnlyOrEntrypoint instanceof Entrypoint
|
|
226
279
|
? newOnlyOrEntrypoint
|
|
227
|
-
: new Entrypoint(this.services, this.parents, this.initialCode, this.name, newOnlyOrEntrypoint, this.exports, this.evaluatedOnly, this.loadedAndParsed, this.resolveTasks, this.dependencies, this.generation + 1);
|
|
280
|
+
: new Entrypoint(this.services, this.parents, this.initialCode, this.name, newOnlyOrEntrypoint, this.exports, this.evaluatedOnly, this.loadedAndParsed, this.resolveTasks, this.dependencies, this.invalidationDependencies, this.invalidateOnDependencyChange, this.generation + 1);
|
|
228
281
|
this.services.eventEmitter.entrypointEvent(this.seqId, {
|
|
229
282
|
type: 'superseded',
|
|
230
283
|
with: newEntrypoint.seqId,
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { File } from '@babel/types';
|
|
2
|
+
export type BarrelSkipReason = 'custom-evaluator' | 'empty' | 'ignored' | 'impure' | 'namespace-barrel' | 'unknown-star';
|
|
3
|
+
export type BarrelBlockedReason = 'ambiguous' | 'cycle' | 'namespace-barrel' | 'unknown-star' | 'unresolved';
|
|
4
|
+
export type BarrelResolvedBinding = {
|
|
5
|
+
imported: string;
|
|
6
|
+
kind: 'named';
|
|
7
|
+
source: string;
|
|
8
|
+
} | {
|
|
9
|
+
kind: 'namespace';
|
|
10
|
+
source: string;
|
|
11
|
+
};
|
|
12
|
+
export type BarrelManifestExport = BarrelResolvedBinding | {
|
|
13
|
+
kind: 'blocked';
|
|
14
|
+
reason: BarrelBlockedReason;
|
|
15
|
+
};
|
|
16
|
+
export type BarrelManifest = {
|
|
17
|
+
complete: boolean;
|
|
18
|
+
exports: Record<string, BarrelManifestExport>;
|
|
19
|
+
kind: 'barrel';
|
|
20
|
+
};
|
|
21
|
+
export type BarrelManifestCacheEntry = BarrelManifest | {
|
|
22
|
+
kind: 'ineligible';
|
|
23
|
+
reason: BarrelSkipReason;
|
|
24
|
+
};
|
|
25
|
+
export type RawBarrelReexport = {
|
|
26
|
+
exported: string;
|
|
27
|
+
imported: string;
|
|
28
|
+
kind: 'named';
|
|
29
|
+
source: string;
|
|
30
|
+
} | {
|
|
31
|
+
exported: string;
|
|
32
|
+
kind: 'namespace';
|
|
33
|
+
source: string;
|
|
34
|
+
};
|
|
35
|
+
export type RawBarrelManifest = {
|
|
36
|
+
complete: boolean;
|
|
37
|
+
explicitExports: string[];
|
|
38
|
+
exportAll: string[];
|
|
39
|
+
kind: 'barrel';
|
|
40
|
+
reexports: RawBarrelReexport[];
|
|
41
|
+
};
|
|
42
|
+
export declare function analyzeBarrelFile(ast: File): BarrelManifestCacheEntry | RawBarrelManifest;
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.analyzeBarrelFile = analyzeBarrelFile;
|
|
7
|
+
/* eslint-disable no-continue, @typescript-eslint/no-use-before-define */
|
|
8
|
+
const traverse_1 = __importDefault(require("@babel/traverse"));
|
|
9
|
+
const types_1 = require("@babel/types");
|
|
10
|
+
const isTypeOnlyImport = (statement) => {
|
|
11
|
+
if (statement.importKind === 'type') {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
if (statement.specifiers.length === 0) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return statement.specifiers.every((specifier) => specifier.type === 'ImportSpecifier' && specifier.importKind === 'type');
|
|
18
|
+
};
|
|
19
|
+
const isTypeOnlyExport = (statement) => statement.exportKind === 'type';
|
|
20
|
+
const getModuleExportName = (node) => node.type === 'Identifier' ? node.name : node.value;
|
|
21
|
+
const isTypeOnlyStatement = (statement) => {
|
|
22
|
+
switch (statement.type) {
|
|
23
|
+
case 'EmptyStatement':
|
|
24
|
+
case 'TSDeclareFunction':
|
|
25
|
+
case 'TSInterfaceDeclaration':
|
|
26
|
+
case 'TSTypeAliasDeclaration':
|
|
27
|
+
return true;
|
|
28
|
+
default:
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
function collectExportNamedDeclaration(statement, reexports, explicitExports) {
|
|
33
|
+
if (!statement.source) {
|
|
34
|
+
return isTypeOnlyExport(statement);
|
|
35
|
+
}
|
|
36
|
+
if (isTypeOnlyExport(statement)) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
const source = statement.source.value;
|
|
40
|
+
for (const specifier of statement.specifiers) {
|
|
41
|
+
if (specifier.type === 'ExportSpecifier') {
|
|
42
|
+
if (specifier.exportKind === 'type') {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
explicitExports.add(getModuleExportName(specifier.exported));
|
|
46
|
+
reexports.push(getNamedReexport(specifier, source));
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (specifier.type === 'ExportDefaultSpecifier') {
|
|
50
|
+
explicitExports.add(getModuleExportName(specifier.exported));
|
|
51
|
+
reexports.push(getDefaultReexport(specifier, source));
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (specifier.type === 'ExportNamespaceSpecifier') {
|
|
55
|
+
explicitExports.add(getModuleExportName(specifier.exported));
|
|
56
|
+
reexports.push(getNamespaceReexport(specifier, source));
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
return statement.specifiers.length > 0;
|
|
62
|
+
}
|
|
63
|
+
function getNamedReexport(specifier, source) {
|
|
64
|
+
return {
|
|
65
|
+
exported: getModuleExportName(specifier.exported),
|
|
66
|
+
imported: getModuleExportName(specifier.local),
|
|
67
|
+
kind: 'named',
|
|
68
|
+
source,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function getDefaultReexport(specifier, source) {
|
|
72
|
+
return {
|
|
73
|
+
exported: getModuleExportName(specifier.exported),
|
|
74
|
+
imported: 'default',
|
|
75
|
+
kind: 'named',
|
|
76
|
+
source,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function getNamespaceReexport(specifier, source) {
|
|
80
|
+
return {
|
|
81
|
+
exported: getModuleExportName(specifier.exported),
|
|
82
|
+
kind: 'namespace',
|
|
83
|
+
source,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const collectImportBinding = (statement, imports) => {
|
|
87
|
+
if (statement.importKind === 'type') {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
if (statement.specifiers.length === 0) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
let sawValueImport = false;
|
|
94
|
+
for (const specifier of statement.specifiers) {
|
|
95
|
+
if (specifier.type === 'ImportSpecifier' &&
|
|
96
|
+
specifier.importKind === 'type') {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
sawValueImport = true;
|
|
100
|
+
if (specifier.type === 'ImportSpecifier') {
|
|
101
|
+
imports.set(specifier.local.name, {
|
|
102
|
+
imported: getImportSpecifierName(specifier),
|
|
103
|
+
kind: 'named',
|
|
104
|
+
source: statement.source.value,
|
|
105
|
+
});
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
if (specifier.type === 'ImportDefaultSpecifier') {
|
|
109
|
+
imports.set(specifier.local.name, {
|
|
110
|
+
imported: 'default',
|
|
111
|
+
kind: 'named',
|
|
112
|
+
source: statement.source.value,
|
|
113
|
+
});
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
imports.set(specifier.local.name, {
|
|
117
|
+
kind: 'namespace',
|
|
118
|
+
source: statement.source.value,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return sawValueImport || isTypeOnlyImport(statement);
|
|
122
|
+
};
|
|
123
|
+
const getImportSpecifierName = (specifier) => getModuleExportName(specifier.imported);
|
|
124
|
+
const getLocalDeclarationNames = (declaration) => {
|
|
125
|
+
if (declaration.type === 'VariableDeclaration' ||
|
|
126
|
+
declaration.type === 'FunctionDeclaration' ||
|
|
127
|
+
declaration.type === 'ClassDeclaration') {
|
|
128
|
+
return Object.keys((0, types_1.getBindingIdentifiers)(declaration));
|
|
129
|
+
}
|
|
130
|
+
if (declaration.type === 'TSEnumDeclaration' ||
|
|
131
|
+
declaration.type === 'TSModuleDeclaration') {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
return [];
|
|
135
|
+
};
|
|
136
|
+
const collectLocalExportNamedDeclaration = (statement, importedBindings, passthroughCandidates, explicitExports) => {
|
|
137
|
+
let complete = true;
|
|
138
|
+
if (isTypeOnlyExport(statement)) {
|
|
139
|
+
return {
|
|
140
|
+
complete: true,
|
|
141
|
+
ok: true,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
if (statement.declaration) {
|
|
145
|
+
const names = getLocalDeclarationNames(statement.declaration);
|
|
146
|
+
if (names === null) {
|
|
147
|
+
return {
|
|
148
|
+
complete: false,
|
|
149
|
+
ok: false,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
for (const name of names) {
|
|
153
|
+
explicitExports.add(name);
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
complete: names.length === 0,
|
|
157
|
+
ok: true,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
for (const specifier of statement.specifiers) {
|
|
161
|
+
if (specifier.type !== 'ExportSpecifier') {
|
|
162
|
+
return {
|
|
163
|
+
complete: false,
|
|
164
|
+
ok: false,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
if (specifier.exportKind === 'type') {
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
const exported = getModuleExportName(specifier.exported);
|
|
171
|
+
explicitExports.add(exported);
|
|
172
|
+
if (specifier.local.type !== 'Identifier') {
|
|
173
|
+
complete = false;
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (!importedBindings.has(specifier.local.name)) {
|
|
177
|
+
complete = false;
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
if (!passthroughCandidates.has(specifier.local.name)) {
|
|
181
|
+
passthroughCandidates.set(specifier.local.name, []);
|
|
182
|
+
}
|
|
183
|
+
passthroughCandidates.get(specifier.local.name).push(exported);
|
|
184
|
+
}
|
|
185
|
+
return {
|
|
186
|
+
complete: complete && statement.specifiers.length > 0,
|
|
187
|
+
ok: true,
|
|
188
|
+
};
|
|
189
|
+
};
|
|
190
|
+
const collectPassthroughReexports = (ast, importedBindings, passthroughCandidates, reexports) => {
|
|
191
|
+
let complete = true;
|
|
192
|
+
const bindingReferenceCounts = new Map();
|
|
193
|
+
(0, traverse_1.default)(ast, {
|
|
194
|
+
Program(path) {
|
|
195
|
+
for (const localName of passthroughCandidates.keys()) {
|
|
196
|
+
bindingReferenceCounts.set(localName, path.scope.getBinding(localName)?.referencePaths.length ?? -1);
|
|
197
|
+
}
|
|
198
|
+
path.stop();
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
for (const [localName, exportedNames] of passthroughCandidates) {
|
|
202
|
+
if (bindingReferenceCounts.get(localName) !== exportedNames.length) {
|
|
203
|
+
complete = false;
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
const imported = importedBindings.get(localName);
|
|
207
|
+
for (const exported of exportedNames) {
|
|
208
|
+
if (imported.kind === 'namespace') {
|
|
209
|
+
reexports.push({
|
|
210
|
+
exported,
|
|
211
|
+
kind: 'namespace',
|
|
212
|
+
source: imported.source,
|
|
213
|
+
});
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
reexports.push({
|
|
217
|
+
exported,
|
|
218
|
+
imported: imported.imported,
|
|
219
|
+
kind: 'named',
|
|
220
|
+
source: imported.source,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
complete,
|
|
226
|
+
ok: true,
|
|
227
|
+
};
|
|
228
|
+
};
|
|
229
|
+
function analyzeBarrelProgram(ast) {
|
|
230
|
+
const reexports = [];
|
|
231
|
+
const explicitExports = new Set();
|
|
232
|
+
const exportAll = [];
|
|
233
|
+
const importedBindings = new Map();
|
|
234
|
+
const passthroughCandidates = new Map();
|
|
235
|
+
let complete = true;
|
|
236
|
+
for (const statement of ast.program.body) {
|
|
237
|
+
if (statement.type === 'ImportDeclaration') {
|
|
238
|
+
if (!collectImportBinding(statement, importedBindings)) {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
if (statement.type === 'ExportNamedDeclaration') {
|
|
244
|
+
if (statement.source) {
|
|
245
|
+
if (!collectExportNamedDeclaration(statement, reexports, explicitExports)) {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
const localResult = collectLocalExportNamedDeclaration(statement, importedBindings, passthroughCandidates, explicitExports);
|
|
251
|
+
if (!localResult.ok) {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
complete = complete && localResult.complete;
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
if (statement.type === 'ExportAllDeclaration') {
|
|
258
|
+
if (statement.exportKind === 'type') {
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
if (!statement.source) {
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
exportAll.push(getExportAllSource(statement));
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
if (statement.type === 'ExportDefaultDeclaration') {
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
if (!isTypeOnlyStatement(statement)) {
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
const passthroughResult = collectPassthroughReexports(ast, importedBindings, passthroughCandidates, reexports);
|
|
275
|
+
if (!passthroughResult.ok) {
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
complete = complete && passthroughResult.complete;
|
|
279
|
+
if (reexports.length === 0 && exportAll.length === 0) {
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
return {
|
|
283
|
+
complete,
|
|
284
|
+
explicitExports: [...explicitExports],
|
|
285
|
+
exportAll,
|
|
286
|
+
kind: 'barrel',
|
|
287
|
+
reexports,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
const getExportAllSource = (statement) => statement.source.value;
|
|
291
|
+
function analyzeBarrelFile(ast) {
|
|
292
|
+
const result = analyzeBarrelProgram(ast);
|
|
293
|
+
if (!result) {
|
|
294
|
+
return {
|
|
295
|
+
kind: 'ineligible',
|
|
296
|
+
reason: 'impure',
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
return result;
|
|
300
|
+
}
|
|
@@ -52,11 +52,16 @@ function* getExports() {
|
|
|
52
52
|
const resolvedImports = yield* this.getNext('resolveImports', entrypoint, {
|
|
53
53
|
imports: new Map(withWildcardReexport.map((i) => [i.source, []])),
|
|
54
54
|
});
|
|
55
|
+
const dependencyFilenames = resolvedImports.flatMap((dependency) => dependency.resolved ? [dependency.resolved] : []);
|
|
55
56
|
const importedEntrypoints = findExportsInImports(entrypoint, resolvedImports);
|
|
56
57
|
for (const importedEntrypoint of importedEntrypoints) {
|
|
57
58
|
const exports = yield* this.getNext('getExports', importedEntrypoint.entrypoint, undefined);
|
|
58
59
|
result.push(...exports);
|
|
59
60
|
}
|
|
61
|
+
cache.add('exports', entrypoint.name, result);
|
|
62
|
+
cache.setCacheDependencies('exports', entrypoint.name, dependencyFilenames);
|
|
63
|
+
entrypoint.log(`exports: %o`, result);
|
|
64
|
+
return result;
|
|
60
65
|
}
|
|
61
66
|
entrypoint.log(`exports: %o`, result);
|
|
62
67
|
cache.add('exports', entrypoint.name, result);
|
|
@@ -53,7 +53,17 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
53
53
|
});
|
|
54
54
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
55
55
|
exports.processEntrypoint = processEntrypoint;
|
|
56
|
+
const shaker_1 = require("../../shaker");
|
|
56
57
|
const AbortError_1 = require("../actions/AbortError");
|
|
58
|
+
const barrelManifest_1 = require("../barrelManifest");
|
|
59
|
+
const shouldSkipExplodeReexports = (action) => {
|
|
60
|
+
const { loadedAndParsed } = action.entrypoint;
|
|
61
|
+
if (loadedAndParsed.evaluator !== shaker_1.shaker || !loadedAndParsed.ast) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
const barrelAnalysis = (0, barrelManifest_1.analyzeBarrelFile)(loadedAndParsed.ast);
|
|
65
|
+
return barrelAnalysis.kind === 'barrel' && barrelAnalysis.complete;
|
|
66
|
+
};
|
|
57
67
|
/**
|
|
58
68
|
* The first stage of processing an entrypoint.
|
|
59
69
|
* This stage is responsible for:
|
|
@@ -64,14 +74,26 @@ const AbortError_1 = require("../actions/AbortError");
|
|
|
64
74
|
function* processEntrypoint() {
|
|
65
75
|
const { only, log } = this.entrypoint;
|
|
66
76
|
log('start processing (only: %o)', only);
|
|
77
|
+
this.entrypoint.beginProcessing();
|
|
67
78
|
try {
|
|
68
79
|
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
69
80
|
try {
|
|
70
81
|
const abortSignal = __addDisposableResource(env_1, this.createAbortSignal(), false);
|
|
71
|
-
|
|
82
|
+
if (shouldSkipExplodeReexports(this)) {
|
|
83
|
+
log('skip explodeReexports for pure barrel');
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
yield ['explodeReexports', this.entrypoint, undefined, abortSignal];
|
|
87
|
+
}
|
|
72
88
|
const result = yield* this.getNext('transform', this.entrypoint, undefined, abortSignal);
|
|
73
89
|
this.entrypoint.assertNotSuperseded();
|
|
74
90
|
this.entrypoint.setTransformResult(result);
|
|
91
|
+
const supersededWith = this.entrypoint.applyDeferredSupersede();
|
|
92
|
+
if (supersededWith) {
|
|
93
|
+
log('processing finished, deferred only detected; schedule next attempt');
|
|
94
|
+
yield* this.getNext('processEntrypoint', supersededWith, undefined, null);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
75
97
|
log('entrypoint processing finished');
|
|
76
98
|
}
|
|
77
99
|
catch (e_1) {
|
|
@@ -91,4 +113,7 @@ function* processEntrypoint() {
|
|
|
91
113
|
log(`Unhandled error: %O`, e);
|
|
92
114
|
throw e;
|
|
93
115
|
}
|
|
116
|
+
finally {
|
|
117
|
+
this.entrypoint.endProcessing();
|
|
118
|
+
}
|
|
94
119
|
}
|