@wyw-in-js/transform 1.0.6 → 1.0.8

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.
Files changed (98) hide show
  1. package/esm/cache.js +160 -12
  2. package/esm/cache.js.map +1 -1
  3. package/esm/debug/fileReporter.js.map +1 -1
  4. package/esm/module.js +59 -5
  5. package/esm/module.js.map +1 -1
  6. package/esm/plugins/shaker.js +152 -13
  7. package/esm/plugins/shaker.js.map +1 -1
  8. package/esm/shaker.js +51 -23
  9. package/esm/shaker.js.map +1 -1
  10. package/esm/transform/BaseEntrypoint.js +3 -1
  11. package/esm/transform/BaseEntrypoint.js.map +1 -1
  12. package/esm/transform/Entrypoint.js +68 -20
  13. package/esm/transform/Entrypoint.js.map +1 -1
  14. package/esm/transform/EvaluatedEntrypoint.js.map +1 -1
  15. package/esm/transform/actions/BaseAction.js +2 -1
  16. package/esm/transform/actions/BaseAction.js.map +1 -1
  17. package/esm/transform/actions/actionRunner.js +2 -2
  18. package/esm/transform/actions/actionRunner.js.map +1 -1
  19. package/esm/transform/barrelManifest.js +291 -0
  20. package/esm/transform/barrelManifest.js.map +1 -0
  21. package/esm/transform/generators/getExports.js +5 -0
  22. package/esm/transform/generators/getExports.js.map +1 -1
  23. package/esm/transform/generators/processEntrypoint.js +31 -1
  24. package/esm/transform/generators/processEntrypoint.js.map +1 -1
  25. package/esm/transform/generators/resolveImports.js +29 -5
  26. package/esm/transform/generators/resolveImports.js.map +1 -1
  27. package/esm/transform/generators/rewriteBarrelImports.js +733 -0
  28. package/esm/transform/generators/rewriteBarrelImports.js.map +1 -0
  29. package/esm/transform/generators/transform.js +154 -21
  30. package/esm/transform/generators/transform.js.map +1 -1
  31. package/esm/transform/types.js.map +1 -1
  32. package/esm/transform.js +45 -23
  33. package/esm/transform.js.map +1 -1
  34. package/esm/utils/collectTemplateDependencies.js +9 -0
  35. package/esm/utils/collectTemplateDependencies.js.map +1 -1
  36. package/lib/cache.js +163 -12
  37. package/lib/cache.js.map +1 -1
  38. package/lib/debug/fileReporter.js.map +1 -1
  39. package/lib/module.js +61 -7
  40. package/lib/module.js.map +1 -1
  41. package/lib/plugins/shaker.js +152 -13
  42. package/lib/plugins/shaker.js.map +1 -1
  43. package/lib/shaker.js +58 -26
  44. package/lib/shaker.js.map +1 -1
  45. package/lib/transform/BaseEntrypoint.js +3 -1
  46. package/lib/transform/BaseEntrypoint.js.map +1 -1
  47. package/lib/transform/Entrypoint.js +69 -20
  48. package/lib/transform/Entrypoint.js.map +1 -1
  49. package/lib/transform/EvaluatedEntrypoint.js.map +1 -1
  50. package/lib/transform/actions/BaseAction.js +2 -1
  51. package/lib/transform/actions/BaseAction.js.map +1 -1
  52. package/lib/transform/actions/actionRunner.js +2 -2
  53. package/lib/transform/actions/actionRunner.js.map +1 -1
  54. package/lib/transform/barrelManifest.js +300 -0
  55. package/lib/transform/barrelManifest.js.map +1 -0
  56. package/lib/transform/generators/getExports.js +5 -0
  57. package/lib/transform/generators/getExports.js.map +1 -1
  58. package/lib/transform/generators/processEntrypoint.js +31 -1
  59. package/lib/transform/generators/processEntrypoint.js.map +1 -1
  60. package/lib/transform/generators/resolveImports.js +29 -5
  61. package/lib/transform/generators/resolveImports.js.map +1 -1
  62. package/lib/transform/generators/rewriteBarrelImports.js +743 -0
  63. package/lib/transform/generators/rewriteBarrelImports.js.map +1 -0
  64. package/lib/transform/generators/transform.js +158 -22
  65. package/lib/transform/generators/transform.js.map +1 -1
  66. package/lib/transform/types.js.map +1 -1
  67. package/lib/transform.js +45 -23
  68. package/lib/transform.js.map +1 -1
  69. package/lib/utils/collectTemplateDependencies.js +9 -0
  70. package/lib/utils/collectTemplateDependencies.js.map +1 -1
  71. package/package.json +8 -4
  72. package/types/cache.d.ts +23 -2
  73. package/types/cache.js +170 -10
  74. package/types/debug/fileReporter.d.ts +1 -0
  75. package/types/module.d.ts +3 -0
  76. package/types/module.js +65 -5
  77. package/types/plugins/shaker.js +161 -16
  78. package/types/shaker.d.ts +10 -1
  79. package/types/shaker.js +56 -28
  80. package/types/transform/BaseEntrypoint.d.ts +3 -1
  81. package/types/transform/BaseEntrypoint.js +5 -1
  82. package/types/transform/Entrypoint.d.ts +10 -1
  83. package/types/transform/Entrypoint.js +81 -23
  84. package/types/transform/EvaluatedEntrypoint.d.ts +2 -0
  85. package/types/transform/actions/BaseAction.d.ts +2 -1
  86. package/types/transform/actions/BaseAction.js +3 -1
  87. package/types/transform/actions/actionRunner.js +2 -2
  88. package/types/transform/barrelManifest.d.ts +42 -0
  89. package/types/transform/barrelManifest.js +300 -0
  90. package/types/transform/generators/getExports.js +5 -0
  91. package/types/transform/generators/processEntrypoint.js +29 -1
  92. package/types/transform/generators/resolveImports.js +29 -5
  93. package/types/transform/generators/rewriteBarrelImports.d.ts +15 -0
  94. package/types/transform/generators/rewriteBarrelImports.js +815 -0
  95. package/types/transform/generators/transform.js +148 -19
  96. package/types/transform/types.d.ts +3 -0
  97. package/types/transform.js +47 -23
  98. package/types/utils/collectTemplateDependencies.js +9 -0
@@ -9,8 +9,10 @@ exports.transform = transform;
9
9
  const buildOptions_1 = require("../../options/buildOptions");
10
10
  const dynamic_import_1 = __importDefault(require("../../plugins/dynamic-import"));
11
11
  const preeval_1 = __importDefault(require("../../plugins/preeval"));
12
+ const shaker_1 = require("../../shaker");
12
13
  const TransformMetadata_1 = require("../../utils/TransformMetadata");
13
14
  const getPluginKey_1 = require("../../utils/getPluginKey");
15
+ const rewriteBarrelImports_1 = require("./rewriteBarrelImports");
14
16
  const EMPTY_FILE = '=== empty file ===';
15
17
  const hasKeyInList = (plugin, list) => {
16
18
  const pluginKey = (0, getPluginKey_1.getPluginKey)(plugin);
@@ -41,34 +43,57 @@ function runPreevalStage(babel, evalConfig, pluginOptions, code, originalAst, ev
41
43
  }
42
44
  return result;
43
45
  }
44
- const prepareCode = (services, item, originalAst) => {
45
- const { log, only, loadedAndParsed } = item;
46
+ const isPrevalOnly = (only) => only.length === 1 && only[0] === '__wywPreval';
47
+ const prepareEvaluatorInput = (services, item, originalAst) => {
48
+ const { only, loadedAndParsed, log } = item;
46
49
  if (loadedAndParsed.evaluator === 'ignored') {
47
- log('is ignored');
48
- return [loadedAndParsed.code ?? '', null, null];
50
+ throw new Error(`Cannot prepare ignored entrypoint ${item.name}`);
49
51
  }
50
- const { code, evalConfig, evaluator } = loadedAndParsed;
52
+ const { code, evalConfig } = loadedAndParsed;
51
53
  const { options, babel, eventEmitter } = services;
52
54
  const { pluginOptions } = options;
53
55
  const preevalStageResult = eventEmitter.perf('transform:preeval', () => runPreevalStage(babel, evalConfig, pluginOptions, code, originalAst, eventEmitter));
54
56
  const transformMetadata = (0, TransformMetadata_1.getTransformMetadata)(preevalStageResult.metadata);
55
- if (only.length === 1 && only[0] === '__wywPreval' && !transformMetadata) {
57
+ if (isPrevalOnly(only) && !transformMetadata) {
56
58
  log('[evaluator:end] no metadata');
57
- return [preevalStageResult.code, null, null];
59
+ return {
60
+ kind: 'short-circuit',
61
+ code: preevalStageResult.code,
62
+ };
58
63
  }
59
64
  log('[preeval] metadata %O', transformMetadata);
60
- log('[evaluator:start] using %s', evaluator.name);
61
- log.extend('source')('%s', preevalStageResult.code);
62
- const evaluatorConfig = {
63
- onlyExports: only,
64
- highPriorityPlugins: pluginOptions.highPriorityPlugins,
65
- features: pluginOptions.features,
66
- importOverrides: pluginOptions.importOverrides,
67
- root: options.root,
65
+ return {
66
+ kind: 'continue',
67
+ ast: preevalStageResult.ast,
68
+ code: preevalStageResult.code,
69
+ evalConfig,
70
+ evaluatorConfig: {
71
+ onlyExports: only,
72
+ highPriorityPlugins: pluginOptions.highPriorityPlugins,
73
+ features: pluginOptions.features,
74
+ importOverrides: pluginOptions.importOverrides,
75
+ root: options.root,
76
+ },
77
+ metadata: transformMetadata ?? null,
68
78
  };
69
- const [, transformedCode, imports] = eventEmitter.perf('transform:evaluator', () => evaluator(evalConfig, preevalStageResult.ast, preevalStageResult.code, evaluatorConfig, babel));
79
+ };
80
+ const prepareCode = (services, item, originalAst) => {
81
+ const { log, loadedAndParsed } = item;
82
+ if (loadedAndParsed.evaluator === 'ignored') {
83
+ log('is ignored');
84
+ return [loadedAndParsed.code ?? '', null, null];
85
+ }
86
+ const { evaluator } = loadedAndParsed;
87
+ const { babel, eventEmitter } = services;
88
+ const prepared = prepareEvaluatorInput(services, item, originalAst);
89
+ if (prepared.kind === 'short-circuit') {
90
+ return [prepared.code, null, null];
91
+ }
92
+ log('[evaluator:start] using %s', evaluator.name);
93
+ log.extend('source')('%s', prepared.code);
94
+ const [, transformedCode, imports] = eventEmitter.perf('transform:evaluator', () => evaluator(prepared.evalConfig, prepared.ast, prepared.code, prepared.evaluatorConfig, babel));
70
95
  log('[evaluator:end]');
71
- return [transformedCode, imports, transformMetadata ?? null];
96
+ return [transformedCode, imports, prepared.metadata];
72
97
  };
73
98
  exports.prepareCode = prepareCode;
74
99
  function* internalTransform(prepareFn) {
@@ -119,6 +144,110 @@ function* internalTransform(prepareFn) {
119
144
  * Prepares the code for evaluation. This includes removing dead and potentially unsafe code.
120
145
  * Emits resolveImports and processImports events.
121
146
  */
122
- function transform() {
123
- return internalTransform.call(this, exports.prepareCode);
147
+ function* transform() {
148
+ const { only, loadedAndParsed, log } = this.entrypoint;
149
+ if (loadedAndParsed.evaluator === 'ignored') {
150
+ log('is ignored');
151
+ return {
152
+ code: loadedAndParsed.code ?? '',
153
+ metadata: null,
154
+ };
155
+ }
156
+ if (loadedAndParsed.evaluator !== shaker_1.shaker) {
157
+ return yield* internalTransform.call(this, exports.prepareCode);
158
+ }
159
+ log('>> (%o)', only);
160
+ const prepared = prepareEvaluatorInput(this.services, this.entrypoint, loadedAndParsed.ast);
161
+ if (prepared.kind === 'short-circuit') {
162
+ if (loadedAndParsed.code === prepared.code) {
163
+ log('<< (%o)\n === no changes ===', only);
164
+ }
165
+ else {
166
+ log('<< (%o)', only);
167
+ log.extend('source')('%s', prepared.code || EMPTY_FILE);
168
+ }
169
+ if (prepared.code === '') {
170
+ log('is skipped');
171
+ return {
172
+ code: loadedAndParsed.code ?? '',
173
+ metadata: null,
174
+ };
175
+ }
176
+ return {
177
+ code: prepared.code,
178
+ metadata: null,
179
+ };
180
+ }
181
+ log('[evaluator:start] using %s', loadedAndParsed.evaluator.name);
182
+ log.extend('source')('%s', prepared.code);
183
+ const { babel, eventEmitter } = this.services;
184
+ const [shakenAst, shakenCode, shakenImports] = eventEmitter.perf('transform:evaluator', () => (0, shaker_1.shakeToESM)(prepared.evalConfig, prepared.ast, prepared.code, prepared.evaluatorConfig, babel));
185
+ let nextAst = shakenAst;
186
+ let nextCode = shakenCode;
187
+ let nextResolvedImports = [];
188
+ if (shakenImports !== null && shakenImports.size > 0) {
189
+ const resolvedImports = yield* this.getNext('resolveImports', this.entrypoint, {
190
+ imports: shakenImports,
191
+ phase: 'initial',
192
+ });
193
+ if (resolvedImports.length > 0) {
194
+ const rewritten = yield* rewriteBarrelImports_1.rewriteOptimizedBarrelImports.call(this, shakenAst, shakenCode, resolvedImports);
195
+ nextAst = rewritten.ast;
196
+ nextCode = rewritten.code;
197
+ if (rewritten.optimizedCount > 0) {
198
+ const fullyRewrittenSources = new Set(rewritten.fullyRewrittenSources);
199
+ const partialFallbackSources = new Set(rewritten.partialFallbackSources);
200
+ for (const dependency of resolvedImports) {
201
+ if (dependency.resolved &&
202
+ (fullyRewrittenSources.has(dependency.source) ||
203
+ partialFallbackSources.has(dependency.source))) {
204
+ if (partialFallbackSources.has(dependency.source)) {
205
+ this.entrypoint.addDependency(dependency);
206
+ }
207
+ else {
208
+ this.entrypoint.addInvalidationDependency(dependency);
209
+ }
210
+ this.entrypoint.markInvalidateOnDependencyChange(dependency.resolved);
211
+ }
212
+ }
213
+ nextResolvedImports = yield* this.getNext('resolveImports', this.entrypoint, {
214
+ imports: rewritten.imports,
215
+ phase: 'rewritten',
216
+ preResolved: rewritten.preResolvedImports,
217
+ });
218
+ }
219
+ else {
220
+ nextResolvedImports = resolvedImports;
221
+ }
222
+ }
223
+ }
224
+ if (nextResolvedImports.length !== 0) {
225
+ yield [
226
+ 'processImports',
227
+ this.entrypoint,
228
+ {
229
+ resolved: nextResolvedImports,
230
+ },
231
+ ];
232
+ }
233
+ const [, preparedCode] = eventEmitter.perf('transform:emitCommonJS', () => (0, shaker_1.emitCommonJS)(prepared.evalConfig, nextAst, nextCode, babel));
234
+ log('[evaluator:end]');
235
+ if (loadedAndParsed.code === preparedCode) {
236
+ log('<< (%o)\n === no changes ===', only);
237
+ }
238
+ else {
239
+ log('<< (%o)', only);
240
+ log.extend('source')('%s', preparedCode || EMPTY_FILE);
241
+ }
242
+ if (preparedCode === '') {
243
+ log('is skipped');
244
+ return {
245
+ code: loadedAndParsed.code ?? '',
246
+ metadata: null,
247
+ };
248
+ }
249
+ return {
250
+ code: preparedCode,
251
+ metadata: prepared.metadata,
252
+ };
124
253
  }
@@ -34,6 +34,7 @@ export type AnyIteratorResult<TMode extends 'async' | 'sync', TResult> = {
34
34
  sync: IteratorResult<YieldArg, TResult>;
35
35
  }[TMode];
36
36
  export interface IBaseAction<TAction extends ActionQueueItem, TResult, TData> extends IBaseNode {
37
+ actionContext: unknown;
37
38
  abortSignal: AbortSignal | null;
38
39
  createAbortSignal: () => AbortSignal & Disposable;
39
40
  data: TData;
@@ -123,6 +124,8 @@ export interface IProcessImportsAction extends IBaseAction<IProcessImportsAction
123
124
  }
124
125
  export interface IResolveImportsAction extends IBaseAction<IResolveImportsAction, IEntrypointDependency[], {
125
126
  imports: Map<string, string[]> | null;
127
+ phase?: 'initial' | 'rewritten';
128
+ preResolved?: IEntrypointDependency[];
126
129
  }> {
127
130
  type: 'resolveImports';
128
131
  }
@@ -21,6 +21,24 @@ const resolveImports_1 = require("./transform/generators/resolveImports");
21
21
  const withDefaultServices_1 = require("./transform/helpers/withDefaultServices");
22
22
  const memoizedSyncResolve = new WeakMap();
23
23
  const memoizedAsyncResolve = new WeakMap();
24
+ const EMPTY_CUSTOM_HANDLERS = {};
25
+ const memoizedActionContexts = new WeakMap();
26
+ const getActionContext = (resolveImportsHandler, customHandlers) => {
27
+ const customHandlersKey = Object.keys(customHandlers).length === 0
28
+ ? EMPTY_CUSTOM_HANDLERS
29
+ : customHandlers;
30
+ let actionContextsByHandlers = memoizedActionContexts.get(resolveImportsHandler);
31
+ if (!actionContextsByHandlers) {
32
+ actionContextsByHandlers = new WeakMap();
33
+ memoizedActionContexts.set(resolveImportsHandler, actionContextsByHandlers);
34
+ }
35
+ let actionContext = actionContextsByHandlers.get(customHandlersKey);
36
+ if (!actionContext) {
37
+ actionContext = {};
38
+ actionContextsByHandlers.set(customHandlersKey, actionContext);
39
+ }
40
+ return actionContext;
41
+ };
24
42
  function transformSync(partialServices, originalCode, syncResolve, customHandlers = {}) {
25
43
  const { options } = partialServices;
26
44
  const pluginOptions = (0, loadWywOptions_1.loadWywOptions)(options.pluginOptions);
@@ -35,6 +53,18 @@ function transformSync(partialServices, originalCode, syncResolve, customHandler
35
53
  // If global cache is disabled, we need to create a new cache for each file
36
54
  services.cache = new cache_1.TransformCacheCollection();
37
55
  }
56
+ if (!memoizedSyncResolve.has(syncResolve)) {
57
+ memoizedSyncResolve.set(syncResolve, function resolveImports() {
58
+ return resolveImports_1.syncResolveImports.call(this, syncResolve);
59
+ });
60
+ }
61
+ const resolveImportsHandler = memoizedSyncResolve.get(syncResolve);
62
+ const actionHandlers = {
63
+ ...generators_1.baseHandlers,
64
+ ...customHandlers,
65
+ resolveImports: resolveImportsHandler,
66
+ };
67
+ const actionContext = getActionContext(resolveImportsHandler, customHandlers);
38
68
  const entrypoint = Entrypoint_1.Entrypoint.createRoot(services, options.filename, ['__wywPreval'], originalCode);
39
69
  if (entrypoint.ignored) {
40
70
  return {
@@ -42,18 +72,9 @@ function transformSync(partialServices, originalCode, syncResolve, customHandler
42
72
  sourceMap: options.inputSourceMap,
43
73
  };
44
74
  }
45
- const workflowAction = entrypoint.createAction('workflow', undefined);
46
- if (!memoizedSyncResolve.has(syncResolve)) {
47
- memoizedSyncResolve.set(syncResolve, function resolveImports() {
48
- return resolveImports_1.syncResolveImports.call(this, syncResolve);
49
- });
50
- }
75
+ const workflowAction = entrypoint.createAction('workflow', undefined, null, actionContext);
51
76
  try {
52
- const result = (0, actionRunner_1.syncActionRunner)(workflowAction, {
53
- ...generators_1.baseHandlers,
54
- ...customHandlers,
55
- resolveImports: memoizedSyncResolve.get(syncResolve),
56
- });
77
+ const result = (0, actionRunner_1.syncActionRunner)(workflowAction, actionHandlers);
57
78
  entrypoint.log('%s is ready', entrypoint.name);
58
79
  return result;
59
80
  }
@@ -92,6 +113,19 @@ async function transform(partialServices, originalCode, asyncResolve, customHand
92
113
  * but the "only" option has changed, the file will be re-processed using
93
114
  * the combined "only" option.
94
115
  */
116
+ if (!memoizedAsyncResolve.has(asyncResolve)) {
117
+ const resolveImports = function resolveImports() {
118
+ return resolveImports_1.asyncResolveImports.call(this, asyncResolve);
119
+ };
120
+ memoizedAsyncResolve.set(asyncResolve, resolveImports);
121
+ }
122
+ const resolveImportsHandler = memoizedAsyncResolve.get(asyncResolve);
123
+ const actionHandlers = {
124
+ ...generators_1.baseHandlers,
125
+ ...customHandlers,
126
+ resolveImports: resolveImportsHandler,
127
+ };
128
+ const actionContext = getActionContext(resolveImportsHandler, customHandlers);
95
129
  const entrypoint = Entrypoint_1.Entrypoint.createRoot(services, options.filename, ['__wywPreval'], originalCode);
96
130
  if (entrypoint.ignored) {
97
131
  return {
@@ -99,19 +133,9 @@ async function transform(partialServices, originalCode, asyncResolve, customHand
99
133
  sourceMap: options.inputSourceMap,
100
134
  };
101
135
  }
102
- const workflowAction = entrypoint.createAction('workflow', undefined);
103
- if (!memoizedAsyncResolve.has(asyncResolve)) {
104
- const resolveImports = function resolveImports() {
105
- return resolveImports_1.asyncResolveImports.call(this, asyncResolve);
106
- };
107
- memoizedAsyncResolve.set(asyncResolve, resolveImports);
108
- }
136
+ const workflowAction = entrypoint.createAction('workflow', undefined, null, actionContext);
109
137
  try {
110
- const result = await (0, actionRunner_1.asyncActionRunner)(workflowAction, {
111
- ...generators_1.baseHandlers,
112
- ...customHandlers,
113
- resolveImports: memoizedAsyncResolve.get(asyncResolve),
114
- });
138
+ const result = await (0, actionRunner_1.asyncActionRunner)(workflowAction, actionHandlers);
115
139
  entrypoint.log('%s is ready', entrypoint.name);
116
140
  return result;
117
141
  }
@@ -18,6 +18,15 @@ const valueToLiteral_1 = require("./valueToLiteral");
18
18
  function staticEval(ex, evaluate = false) {
19
19
  if (!evaluate)
20
20
  return undefined;
21
+ if (ex.isIdentifier()) {
22
+ const binding = ex.scope.getBinding(ex.node.name);
23
+ // Babel may "evaluate" a destructured binding to its source container
24
+ // object/array instead of the bound value, which changes template semantics.
25
+ if (binding?.path.isVariableDeclarator() &&
26
+ !binding.path.get('id').isIdentifier()) {
27
+ return undefined;
28
+ }
29
+ }
21
30
  const result = ex.evaluate();
22
31
  if (result.confident && !(0, shared_1.hasEvalMeta)(result.value)) {
23
32
  return [result.value];