@wyw-in-js/transform 2.0.0-alpha.0 → 2.0.0-alpha.1
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 +7 -0
- package/esm/cache.js.map +1 -1
- package/esm/debug/fileReporter.js +35 -1
- package/esm/debug/fileReporter.js.map +1 -1
- package/esm/eval/broker.js +230 -89
- package/esm/eval/broker.js.map +1 -1
- package/esm/eval/protocol.js.map +1 -1
- package/esm/eval/runner.js +143 -24
- package/esm/eval/runner.js.map +1 -1
- package/esm/module.js +70 -43
- package/esm/module.js.map +1 -1
- package/esm/transform/Entrypoint.types.js.map +1 -1
- package/esm/transform/generators/processEntrypoint.js +35 -20
- package/esm/transform/generators/processEntrypoint.js.map +1 -1
- package/esm/transform/generators/resolveImports.js +48 -2
- package/esm/transform/generators/resolveImports.js.map +1 -1
- package/esm/transform/generators/resolveStaticOxcValues/cache.js +182 -0
- package/esm/transform/generators/resolveStaticOxcValues/cache.js.map +1 -0
- package/esm/transform/generators/resolveStaticOxcValues/candidateResolver.js +146 -0
- package/esm/transform/generators/resolveStaticOxcValues/candidateResolver.js.map +1 -0
- package/esm/transform/generators/resolveStaticOxcValues/dependencies.js +33 -0
- package/esm/transform/generators/resolveStaticOxcValues/dependencies.js.map +1 -0
- package/esm/transform/generators/resolveStaticOxcValues/environment.js +29 -0
- package/esm/transform/generators/resolveStaticOxcValues/environment.js.map +1 -0
- package/esm/transform/generators/resolveStaticOxcValues/exportResolver.js +351 -0
- package/esm/transform/generators/resolveStaticOxcValues/exportResolver.js.map +1 -0
- package/esm/transform/generators/resolveStaticOxcValues/exportTargets.js +253 -0
- package/esm/transform/generators/resolveStaticOxcValues/exportTargets.js.map +1 -0
- package/esm/transform/generators/resolveStaticOxcValues/objectAssign.js +310 -0
- package/esm/transform/generators/resolveStaticOxcValues/objectAssign.js.map +1 -0
- package/esm/transform/generators/resolveStaticOxcValues/objectAssignStaticExport.js +74 -0
- package/esm/transform/generators/resolveStaticOxcValues/objectAssignStaticExport.js.map +1 -0
- package/esm/transform/generators/resolveStaticOxcValues/opaqueRuntime.js +229 -0
- package/esm/transform/generators/resolveStaticOxcValues/opaqueRuntime.js.map +1 -0
- package/esm/transform/generators/resolveStaticOxcValues/processorStaticExport.js +172 -0
- package/esm/transform/generators/resolveStaticOxcValues/processorStaticExport.js.map +1 -0
- package/esm/transform/generators/resolveStaticOxcValues/processorStaticModel.js +476 -0
- package/esm/transform/generators/resolveStaticOxcValues/processorStaticModel.js.map +1 -0
- package/esm/transform/generators/resolveStaticOxcValues/processorTarget.js +55 -0
- package/esm/transform/generators/resolveStaticOxcValues/processorTarget.js.map +1 -0
- package/esm/transform/generators/resolveStaticOxcValues/programAnalysis.js +123 -0
- package/esm/transform/generators/resolveStaticOxcValues/programAnalysis.js.map +1 -0
- package/esm/transform/generators/resolveStaticOxcValues/prune.js +186 -0
- package/esm/transform/generators/resolveStaticOxcValues/prune.js.map +1 -0
- package/esm/transform/generators/resolveStaticOxcValues/resolveStaticOxcPreevalValues.js +183 -0
- package/esm/transform/generators/resolveStaticOxcValues/resolveStaticOxcPreevalValues.js.map +1 -0
- package/esm/transform/generators/resolveStaticOxcValues/staticExpression.js +298 -0
- package/esm/transform/generators/resolveStaticOxcValues/staticExpression.js.map +1 -0
- package/esm/transform/generators/resolveStaticOxcValues/staticExpressionDependencies.js +298 -0
- package/esm/transform/generators/resolveStaticOxcValues/staticExpressionDependencies.js.map +1 -0
- package/esm/transform/generators/resolveStaticOxcValues/types.js +3 -0
- package/esm/transform/generators/resolveStaticOxcValues/types.js.map +1 -0
- package/esm/transform/generators/resolveStaticOxcValues/zeroArgFunctionStaticExport.js +59 -0
- package/esm/transform/generators/resolveStaticOxcValues/zeroArgFunctionStaticExport.js.map +1 -0
- package/esm/transform/generators/resolveStaticOxcValues.js +1 -2910
- package/esm/transform/generators/resolveStaticOxcValues.js.map +1 -1
- package/esm/transform/generators/transform.js +57 -45
- package/esm/transform/generators/transform.js.map +1 -1
- package/esm/transform/helpers/loadWywOptions.js +33 -4
- package/esm/transform/helpers/loadWywOptions.js.map +1 -1
- package/esm/transform.js +3 -1
- package/esm/transform.js.map +1 -1
- package/esm/utils/EventEmitter.js +42 -9
- package/esm/utils/EventEmitter.js.map +1 -1
- package/esm/utils/applyOxcProcessors/applyOxcProcessors.js +160 -0
- package/esm/utils/applyOxcProcessors/applyOxcProcessors.js.map +1 -0
- package/esm/utils/applyOxcProcessors/cleanupBindings.js +157 -0
- package/esm/utils/applyOxcProcessors/cleanupBindings.js.map +1 -0
- package/esm/utils/applyOxcProcessors/cleanupRemovals.js +431 -0
- package/esm/utils/applyOxcProcessors/cleanupRemovals.js.map +1 -0
- package/esm/utils/applyOxcProcessors/displayName.js +93 -0
- package/esm/utils/applyOxcProcessors/displayName.js.map +1 -0
- package/esm/utils/applyOxcProcessors/expressionValues.js +152 -0
- package/esm/utils/applyOxcProcessors/expressionValues.js.map +1 -0
- package/esm/utils/applyOxcProcessors/processorFactory.js +62 -0
- package/esm/utils/applyOxcProcessors/processorFactory.js.map +1 -0
- package/esm/utils/applyOxcProcessors/processorUsages.js +143 -0
- package/esm/utils/applyOxcProcessors/processorUsages.js.map +1 -0
- package/esm/utils/applyOxcProcessors/sameFileStaticValues.js +207 -0
- package/esm/utils/applyOxcProcessors/sameFileStaticValues.js.map +1 -0
- package/esm/utils/applyOxcProcessors/shared.js +29 -0
- package/esm/utils/applyOxcProcessors/shared.js.map +1 -0
- package/esm/utils/applyOxcProcessors/types.js +2 -0
- package/esm/utils/applyOxcProcessors/types.js.map +1 -0
- package/esm/utils/applyOxcProcessors.js +1 -1216
- package/esm/utils/applyOxcProcessors.js.map +1 -1
- package/esm/utils/collectOxcRuntime/normalizeRuntimeCode.js +157 -0
- package/esm/utils/collectOxcRuntime/normalizeRuntimeCode.js.map +1 -0
- package/esm/utils/collectOxcRuntime/sourceMap.js +36 -0
- package/esm/utils/collectOxcRuntime/sourceMap.js.map +1 -0
- package/esm/utils/collectOxcRuntime/types.js +2 -0
- package/esm/utils/collectOxcRuntime/types.js.map +1 -0
- package/esm/utils/collectOxcRuntime.js +5 -193
- package/esm/utils/collectOxcRuntime.js.map +1 -1
- package/esm/utils/collectOxcTemplateDependencies/expressionExtraction.js +496 -0
- package/esm/utils/collectOxcTemplateDependencies/expressionExtraction.js.map +1 -0
- package/esm/utils/collectOxcTemplateDependencies/expressionReplacements.js +113 -0
- package/esm/utils/collectOxcTemplateDependencies/expressionReplacements.js.map +1 -0
- package/esm/utils/collectOxcTemplateDependencies/scopeAnalysis.js +387 -0
- package/esm/utils/collectOxcTemplateDependencies/scopeAnalysis.js.map +1 -0
- package/esm/utils/collectOxcTemplateDependencies/staticBindings.js +17 -0
- package/esm/utils/collectOxcTemplateDependencies/staticBindings.js.map +1 -0
- package/esm/utils/collectOxcTemplateDependencies/staticEvaluator.js +540 -0
- package/esm/utils/collectOxcTemplateDependencies/staticEvaluator.js.map +1 -0
- package/esm/utils/collectOxcTemplateDependencies/types.js +2 -0
- package/esm/utils/collectOxcTemplateDependencies/types.js.map +1 -0
- package/esm/utils/collectOxcTemplateDependencies.js +3 -1397
- package/esm/utils/collectOxcTemplateDependencies.js.map +1 -1
- package/esm/utils/nativeResolver.js +93 -0
- package/esm/utils/nativeResolver.js.map +1 -0
- package/esm/utils/oxc/ast.js +28 -0
- package/esm/utils/oxc/ast.js.map +1 -0
- package/esm/utils/oxc/parse.js +3 -0
- package/esm/utils/oxc/parse.js.map +1 -0
- package/esm/utils/oxc/replacements.js +14 -0
- package/esm/utils/oxc/replacements.js.map +1 -0
- package/esm/utils/oxc/sourceLocations.js +59 -0
- package/esm/utils/oxc/sourceLocations.js.map +1 -0
- package/esm/utils/oxcPreevalStage/evalStrategy.js +3 -0
- package/esm/utils/oxcPreevalStage/evalStrategy.js.map +1 -0
- package/esm/utils/oxcPreevalStage/prepareCode.js +21 -0
- package/esm/utils/oxcPreevalStage/prepareCode.js.map +1 -0
- package/esm/utils/oxcPreevalStage/prevalExport.js +23 -0
- package/esm/utils/oxcPreevalStage/prevalExport.js.map +1 -0
- package/esm/utils/oxcPreevalStage/processors.js +17 -0
- package/esm/utils/oxcPreevalStage/processors.js.map +1 -0
- package/esm/utils/oxcPreevalStage/staticOverlay.js +18 -0
- package/esm/utils/oxcPreevalStage/staticOverlay.js.map +1 -0
- package/esm/utils/oxcPreevalStage/types.js +2 -0
- package/esm/utils/oxcPreevalStage/types.js.map +1 -0
- package/esm/utils/oxcPreevalStage.js +17 -73
- package/esm/utils/oxcPreevalStage.js.map +1 -1
- package/esm/utils/oxcPreevalTransforms.js +12 -1
- package/esm/utils/oxcPreevalTransforms.js.map +1 -1
- package/esm/utils/processorStaticSemantics.js +157 -0
- package/esm/utils/processorStaticSemantics.js.map +1 -0
- package/esm/utils/resolveWithConditions.js +3 -3
- package/esm/utils/resolveWithConditions.js.map +1 -1
- package/package.json +4 -3
- package/types/cache.js +8 -0
- package/types/debug/fileReporter.js +46 -1
- package/types/eval/broker.d.ts +6 -2
- package/types/eval/broker.js +244 -95
- package/types/eval/protocol.d.ts +15 -1
- package/types/module.d.ts +4 -1
- package/types/module.js +97 -48
- package/types/transform/Entrypoint.types.d.ts +3 -0
- package/types/transform/generators/resolveImports.d.ts +3 -1
- package/types/transform/generators/resolveImports.js +49 -2
- package/types/transform/generators/resolveStaticOxcValues/cache.d.ts +25 -0
- package/types/transform/generators/resolveStaticOxcValues/cache.js +182 -0
- package/types/transform/generators/resolveStaticOxcValues/candidateResolver.d.ts +5 -0
- package/types/transform/generators/resolveStaticOxcValues/candidateResolver.js +149 -0
- package/types/transform/generators/resolveStaticOxcValues/dependencies.d.ts +6 -0
- package/types/transform/generators/resolveStaticOxcValues/dependencies.js +37 -0
- package/types/transform/generators/resolveStaticOxcValues/environment.d.ts +12 -0
- package/types/transform/generators/resolveStaticOxcValues/environment.js +32 -0
- package/types/transform/generators/resolveStaticOxcValues/exportResolver.d.ts +4 -0
- package/types/transform/generators/resolveStaticOxcValues/exportResolver.js +358 -0
- package/types/transform/generators/resolveStaticOxcValues/exportTargets.d.ts +20 -0
- package/types/transform/generators/resolveStaticOxcValues/exportTargets.js +285 -0
- package/types/transform/generators/resolveStaticOxcValues/objectAssign.d.ts +41 -0
- package/types/transform/generators/resolveStaticOxcValues/objectAssign.js +352 -0
- package/types/transform/generators/resolveStaticOxcValues/objectAssignStaticExport.d.ts +6 -0
- package/types/transform/generators/resolveStaticOxcValues/objectAssignStaticExport.js +88 -0
- package/types/transform/generators/resolveStaticOxcValues/opaqueRuntime.d.ts +13 -0
- package/types/transform/generators/resolveStaticOxcValues/opaqueRuntime.js +263 -0
- package/types/transform/generators/resolveStaticOxcValues/processorStaticExport.d.ts +4 -0
- package/types/transform/generators/resolveStaticOxcValues/processorStaticExport.js +191 -0
- package/types/transform/generators/resolveStaticOxcValues/processorStaticModel.d.ts +40 -0
- package/types/transform/generators/resolveStaticOxcValues/processorStaticModel.js +516 -0
- package/types/transform/generators/resolveStaticOxcValues/processorTarget.d.ts +5 -0
- package/types/transform/generators/resolveStaticOxcValues/processorTarget.js +62 -0
- package/types/transform/generators/resolveStaticOxcValues/programAnalysis.d.ts +11 -0
- package/types/transform/generators/resolveStaticOxcValues/programAnalysis.js +133 -0
- package/types/transform/generators/resolveStaticOxcValues/prune.d.ts +15 -0
- package/types/transform/generators/resolveStaticOxcValues/prune.js +220 -0
- package/types/transform/generators/resolveStaticOxcValues/resolveStaticOxcPreevalValues.d.ts +2 -0
- package/types/transform/generators/resolveStaticOxcValues/resolveStaticOxcPreevalValues.js +197 -0
- package/types/transform/generators/resolveStaticOxcValues/staticExpression.d.ts +25 -0
- package/types/transform/generators/resolveStaticOxcValues/staticExpression.js +391 -0
- package/types/transform/generators/resolveStaticOxcValues/staticExpressionDependencies.d.ts +14 -0
- package/types/transform/generators/resolveStaticOxcValues/staticExpressionDependencies.js +304 -0
- package/types/transform/generators/resolveStaticOxcValues/types.d.ts +99 -0
- package/types/transform/generators/resolveStaticOxcValues/types.js +2 -0
- package/types/transform/generators/resolveStaticOxcValues/zeroArgFunctionStaticExport.d.ts +7 -0
- package/types/transform/generators/resolveStaticOxcValues/zeroArgFunctionStaticExport.js +64 -0
- package/types/transform/generators/resolveStaticOxcValues.d.ts +1 -2
- package/types/transform/generators/resolveStaticOxcValues.js +1 -3235
- package/types/transform/generators/transform.js +63 -49
- package/types/transform/helpers/loadWywOptions.js +23 -3
- package/types/transform.js +3 -1
- package/types/utils/EventEmitter.d.ts +16 -1
- package/types/utils/EventEmitter.js +44 -9
- package/types/utils/applyOxcProcessors/applyOxcProcessors.d.ts +8 -0
- package/types/utils/applyOxcProcessors/applyOxcProcessors.js +167 -0
- package/types/utils/applyOxcProcessors/cleanupBindings.d.ts +12 -0
- package/types/utils/applyOxcProcessors/cleanupBindings.js +189 -0
- package/types/utils/applyOxcProcessors/cleanupRemovals.d.ts +16 -0
- package/types/utils/applyOxcProcessors/cleanupRemovals.js +482 -0
- package/types/utils/applyOxcProcessors/displayName.d.ts +9 -0
- package/types/utils/applyOxcProcessors/displayName.js +113 -0
- package/types/utils/applyOxcProcessors/expressionValues.d.ts +11 -0
- package/types/utils/applyOxcProcessors/expressionValues.js +170 -0
- package/types/utils/applyOxcProcessors/processorFactory.d.ts +7 -0
- package/types/utils/applyOxcProcessors/processorFactory.js +70 -0
- package/types/utils/applyOxcProcessors/processorUsages.d.ts +16 -0
- package/types/utils/applyOxcProcessors/processorUsages.js +163 -0
- package/types/utils/applyOxcProcessors/sameFileStaticValues.d.ts +23 -0
- package/types/utils/applyOxcProcessors/sameFileStaticValues.js +211 -0
- package/types/utils/applyOxcProcessors/shared.d.ts +10 -0
- package/types/utils/applyOxcProcessors/shared.js +37 -0
- package/types/utils/applyOxcProcessors/types.d.ts +88 -0
- package/types/utils/applyOxcProcessors/types.js +1 -0
- package/types/utils/applyOxcProcessors.d.ts +1 -16
- package/types/utils/applyOxcProcessors.js +1 -1391
- package/types/utils/collectOxcRuntime/normalizeRuntimeCode.d.ts +1 -0
- package/types/utils/collectOxcRuntime/normalizeRuntimeCode.js +185 -0
- package/types/utils/collectOxcRuntime/sourceMap.d.ts +2 -0
- package/types/utils/collectOxcRuntime/sourceMap.js +37 -0
- package/types/utils/collectOxcRuntime/types.d.ts +16 -0
- package/types/utils/collectOxcRuntime/types.js +1 -0
- package/types/utils/collectOxcRuntime.d.ts +2 -12
- package/types/utils/collectOxcRuntime.js +5 -224
- package/types/utils/collectOxcTemplateDependencies/expressionExtraction.d.ts +6 -0
- package/types/utils/collectOxcTemplateDependencies/expressionExtraction.js +550 -0
- package/types/utils/collectOxcTemplateDependencies/expressionReplacements.d.ts +11 -0
- package/types/utils/collectOxcTemplateDependencies/expressionReplacements.js +131 -0
- package/types/utils/collectOxcTemplateDependencies/scopeAnalysis.d.ts +20 -0
- package/types/utils/collectOxcTemplateDependencies/scopeAnalysis.js +434 -0
- package/types/utils/collectOxcTemplateDependencies/staticBindings.d.ts +7 -0
- package/types/utils/collectOxcTemplateDependencies/staticBindings.js +13 -0
- package/types/utils/collectOxcTemplateDependencies/staticEvaluator.d.ts +13 -0
- package/types/utils/collectOxcTemplateDependencies/staticEvaluator.js +626 -0
- package/types/utils/collectOxcTemplateDependencies/types.d.ts +116 -0
- package/types/utils/collectOxcTemplateDependencies/types.js +1 -0
- package/types/utils/collectOxcTemplateDependencies.d.ts +4 -38
- package/types/utils/collectOxcTemplateDependencies.js +3 -1580
- package/types/utils/nativeResolver.d.ts +13 -0
- package/types/utils/nativeResolver.js +91 -0
- package/types/utils/oxc/ast.d.ts +4 -0
- package/types/utils/oxc/ast.js +37 -0
- package/types/utils/oxc/parse.d.ts +3 -0
- package/types/utils/oxc/parse.js +2 -0
- package/types/utils/oxc/replacements.d.ts +12 -0
- package/types/utils/oxc/replacements.js +18 -0
- package/types/utils/oxc/sourceLocations.d.ts +5 -0
- package/types/utils/oxc/sourceLocations.js +63 -0
- package/types/utils/oxcPreevalStage/evalStrategy.d.ts +3 -0
- package/types/utils/oxcPreevalStage/evalStrategy.js +2 -0
- package/types/utils/oxcPreevalStage/prepareCode.d.ts +3 -0
- package/types/utils/oxcPreevalStage/prepareCode.js +20 -0
- package/types/utils/oxcPreevalStage/prevalExport.d.ts +1 -0
- package/types/utils/oxcPreevalStage/prevalExport.js +22 -0
- package/types/utils/oxcPreevalStage/processors.d.ts +10 -0
- package/types/utils/oxcPreevalStage/processors.js +16 -0
- package/types/utils/oxcPreevalStage/staticOverlay.d.ts +3 -0
- package/types/utils/oxcPreevalStage/staticOverlay.js +23 -0
- package/types/utils/oxcPreevalStage/types.d.ts +22 -0
- package/types/utils/oxcPreevalStage/types.js +1 -0
- package/types/utils/oxcPreevalStage.d.ts +2 -18
- package/types/utils/oxcPreevalStage.js +17 -79
- package/types/utils/oxcPreevalTransforms.js +14 -1
- package/types/utils/processorStaticSemantics.d.ts +13 -0
- package/types/utils/processorStaticSemantics.js +191 -0
- package/types/utils/resolveWithConditions.js +3 -3
- package/esm/eval/resolverStrategy.js +0 -51
- package/esm/eval/resolverStrategy.js.map +0 -1
- package/types/eval/resolverStrategy.d.ts +0 -13
- package/types/eval/resolverStrategy.js +0 -46
|
@@ -0,0 +1,550 @@
|
|
|
1
|
+
/* eslint-disable no-restricted-syntax,no-continue */
|
|
2
|
+
import { ValueType } from '@wyw-in-js/shared';
|
|
3
|
+
import { applyOxcReplacements } from '../oxc/replacements';
|
|
4
|
+
import { createOxcLocationLookup } from '../oxc/sourceLocations';
|
|
5
|
+
import { analyzeProgram, containsTaggedTemplateExpression, createSpanLookup, findReferences, getSourceLocation, isBindingDeclaredWithin, parseOxc, resolveBindingAt, } from './scopeAnalysis';
|
|
6
|
+
import { applyExpressionReplacements, collectIdentifierReferenceReplacements, collectStaticNamespaceMemberReferences, getConstantReplacement, replaceIdentifierReferences, } from './expressionReplacements';
|
|
7
|
+
import { cloneStaticValue, evaluateStatic, isStaticSerializableValue, literalCode, } from './staticEvaluator';
|
|
8
|
+
const allocateExpressionName = (ctx) => {
|
|
9
|
+
let base = '_exp';
|
|
10
|
+
let idx = 1;
|
|
11
|
+
while (ctx.usedNames.has(base)) {
|
|
12
|
+
idx += 1;
|
|
13
|
+
base = `_exp${idx}`;
|
|
14
|
+
}
|
|
15
|
+
ctx.usedNames.add(base);
|
|
16
|
+
return base;
|
|
17
|
+
};
|
|
18
|
+
const hoistedBindingKey = (binding) => `${binding.scope.start}:${binding.scope.end}:${binding.declaredAt}:${binding.name}`;
|
|
19
|
+
const allocateHoistedBindingName = (originalName, ctx) => {
|
|
20
|
+
const sanitized = originalName.replace(/[^A-Za-z0-9_$]/g, '_') || 'hoisted';
|
|
21
|
+
const base = /^[A-Za-z_$]/.test(sanitized) ? `_${sanitized}` : '_hoisted';
|
|
22
|
+
let candidate = base;
|
|
23
|
+
let idx = 2;
|
|
24
|
+
while (ctx.usedNames.has(candidate)) {
|
|
25
|
+
candidate = `${base}${idx}`;
|
|
26
|
+
idx += 1;
|
|
27
|
+
}
|
|
28
|
+
ctx.usedNames.add(candidate);
|
|
29
|
+
return candidate;
|
|
30
|
+
};
|
|
31
|
+
const getHoistedBindingName = (binding, ctx) => {
|
|
32
|
+
const key = hoistedBindingKey(binding);
|
|
33
|
+
const existing = ctx.hoistedBindingNames.get(key);
|
|
34
|
+
if (existing) {
|
|
35
|
+
return existing;
|
|
36
|
+
}
|
|
37
|
+
const next = allocateHoistedBindingName(binding.name, ctx);
|
|
38
|
+
ctx.hoistedBindingNames.set(key, next);
|
|
39
|
+
return next;
|
|
40
|
+
};
|
|
41
|
+
const parenthesizeStaticReplacement = (source) => `(${source})`;
|
|
42
|
+
const replaceStaticLocalReferences = (expression, replacements, ctx, extraReplacements = []) => {
|
|
43
|
+
if (expression.type === 'Identifier' && extraReplacements.length === 0) {
|
|
44
|
+
return (replacements.get(expression.name) ??
|
|
45
|
+
ctx.code.slice(expression.start, expression.end));
|
|
46
|
+
}
|
|
47
|
+
const parenthesized = new Map();
|
|
48
|
+
replacements.forEach((value, key) => {
|
|
49
|
+
parenthesized.set(key, parenthesizeStaticReplacement(value));
|
|
50
|
+
});
|
|
51
|
+
return applyExpressionReplacements(expression, [
|
|
52
|
+
...extraReplacements,
|
|
53
|
+
...collectIdentifierReferenceReplacements(expression, parenthesized),
|
|
54
|
+
], ctx.code);
|
|
55
|
+
};
|
|
56
|
+
const collectStaticLocalExpression = (expression, ctx, stack = []) => {
|
|
57
|
+
const replacements = new Map();
|
|
58
|
+
const importedFrom = new Set();
|
|
59
|
+
const imports = [];
|
|
60
|
+
for (const { name, start } of findReferences(expression, ctx.referencesByNode)) {
|
|
61
|
+
const binding = resolveBindingAt(ctx, name, start);
|
|
62
|
+
if (!binding) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
if (binding.importedFrom) {
|
|
66
|
+
importedFrom.add(binding.importedFrom);
|
|
67
|
+
if (binding.imported && binding.imported !== '*') {
|
|
68
|
+
imports.push({
|
|
69
|
+
imported: binding.imported,
|
|
70
|
+
local: binding.name,
|
|
71
|
+
source: binding.importedFrom,
|
|
72
|
+
});
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
const replacement = getConstantReplacement(binding, ctx);
|
|
78
|
+
if (replacement) {
|
|
79
|
+
replacements.set(name, replacement);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (binding.kind === 'param' ||
|
|
83
|
+
binding.declarationKind !== 'const' ||
|
|
84
|
+
!binding.declarator?.init ||
|
|
85
|
+
binding.declarator.id.type !== 'Identifier') {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
// Processor-managed bindings (const x = css``) carry their value
|
|
89
|
+
// (the generated className string) via inlineConstants at candidate
|
|
90
|
+
// evaluation time. Walking the TaggedTemplateExpression here would
|
|
91
|
+
// pull the processor's tag import (e.g. `css` from '@linaria/core')
|
|
92
|
+
// into the candidate's static imports, where it fails to resolve.
|
|
93
|
+
// Leave the identifier as a free reference; the candidate-side env
|
|
94
|
+
// supplies the className.
|
|
95
|
+
if (binding.declarator.init.type === 'TaggedTemplateExpression') {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const key = hoistedBindingKey(binding);
|
|
99
|
+
if (stack.includes(key)) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
const nested = collectStaticLocalExpression(binding.declarator.init, ctx, [
|
|
103
|
+
...stack,
|
|
104
|
+
key,
|
|
105
|
+
]);
|
|
106
|
+
if (!nested) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
replacements.set(name, nested.source);
|
|
110
|
+
nested.importedFrom.forEach((source) => importedFrom.add(source));
|
|
111
|
+
imports.push(...nested.imports);
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
importedFrom: [...importedFrom],
|
|
115
|
+
imports,
|
|
116
|
+
source: replacements.size > 0
|
|
117
|
+
? replaceStaticLocalReferences(expression, replacements, ctx)
|
|
118
|
+
: ctx.code.slice(expression.start, expression.end),
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
const declarationInitCode = (init, ctx) => {
|
|
122
|
+
const renamedDependencies = new Map();
|
|
123
|
+
findReferences(init, ctx.referencesByNode).forEach(({ name, start }) => {
|
|
124
|
+
const dependency = resolveBindingAt(ctx, name, start);
|
|
125
|
+
if (!dependency ||
|
|
126
|
+
dependency.importedFrom ||
|
|
127
|
+
dependency.isRoot ||
|
|
128
|
+
dependency.declarator?.id.type !== 'Identifier') {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
renamedDependencies.set(name, getHoistedBindingName(dependency, ctx));
|
|
132
|
+
});
|
|
133
|
+
return renamedDependencies.size > 0
|
|
134
|
+
? replaceIdentifierReferences(init, renamedDependencies, ctx.code)
|
|
135
|
+
: ctx.code.slice(init.start, init.end);
|
|
136
|
+
};
|
|
137
|
+
const addHoistedCode = (key, code, ctx) => {
|
|
138
|
+
if (ctx.hoistedDeclarations.has(key)) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
ctx.hoistedDeclarations.set(key, code);
|
|
142
|
+
const declarations = ctx.hoistedDeclarationsByInsertionPoint.get(ctx.currentInsertionPoint) ??
|
|
143
|
+
[];
|
|
144
|
+
declarations.push(code);
|
|
145
|
+
ctx.hoistedDeclarationsByInsertionPoint.set(ctx.currentInsertionPoint, declarations);
|
|
146
|
+
};
|
|
147
|
+
const declarationCode = (binding, ctx) => {
|
|
148
|
+
const { declarator } = binding;
|
|
149
|
+
if (!declarator) {
|
|
150
|
+
return '';
|
|
151
|
+
}
|
|
152
|
+
const { id } = declarator;
|
|
153
|
+
if (id.type !== 'Identifier') {
|
|
154
|
+
const idCode = ctx.code.slice(id.start, id.end);
|
|
155
|
+
if (!declarator.init) {
|
|
156
|
+
return `let ${idCode};`;
|
|
157
|
+
}
|
|
158
|
+
return `let ${idCode} = ${declarationInitCode(declarator.init, ctx)};`;
|
|
159
|
+
}
|
|
160
|
+
const hoistedName = getHoistedBindingName(binding, ctx);
|
|
161
|
+
if (!declarator.init) {
|
|
162
|
+
return `let ${hoistedName};`;
|
|
163
|
+
}
|
|
164
|
+
return `let ${hoistedName} = ${declarationInitCode(declarator.init, ctx)};`;
|
|
165
|
+
};
|
|
166
|
+
const assertHoistable = (binding, ctx, stack = []) => {
|
|
167
|
+
if (!binding.declarator?.init || binding.importedFrom || binding.isRoot) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (stack.includes(binding.name)) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const refs = findReferences(binding.declarator.init, ctx.referencesByNode);
|
|
174
|
+
refs.forEach(({ name, start }) => {
|
|
175
|
+
const nextBinding = resolveBindingAt(ctx, name, start);
|
|
176
|
+
if (!nextBinding) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if (nextBinding.kind === 'param') {
|
|
180
|
+
throw new Error(`This identifier cannot be used in the template, because it is a function parameter.`);
|
|
181
|
+
}
|
|
182
|
+
assertHoistable(nextBinding, ctx, [...stack, binding.name]);
|
|
183
|
+
});
|
|
184
|
+
};
|
|
185
|
+
const addHoistedDeclaration = (binding, ctx, stack = []) => {
|
|
186
|
+
if (!binding.declaration ||
|
|
187
|
+
!binding.declarator ||
|
|
188
|
+
binding.importedFrom ||
|
|
189
|
+
binding.isRoot ||
|
|
190
|
+
stack.includes(binding.name)) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const hoistSource = binding.declarator.init ?? binding.declarator;
|
|
194
|
+
findReferences(hoistSource, ctx.referencesByNode).forEach(({ name, start }) => {
|
|
195
|
+
const dependency = resolveBindingAt(ctx, name, start);
|
|
196
|
+
if (dependency) {
|
|
197
|
+
addHoistedDeclaration(dependency, ctx, [...stack, binding.name]);
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
if (!ctx.hoistedDeclarations.has(binding.name)) {
|
|
201
|
+
addHoistedCode(binding.name, declarationCode(binding, ctx), ctx);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
const literalExpressionValue = (expression, ctx) => {
|
|
205
|
+
if (expression.type !== 'Literal') {
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
if (expression.value !== null &&
|
|
209
|
+
typeof expression.value !== 'string' &&
|
|
210
|
+
typeof expression.value !== 'number' &&
|
|
211
|
+
typeof expression.value !== 'boolean') {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
let type;
|
|
215
|
+
if (expression.value === null) {
|
|
216
|
+
type = 'NullLiteral';
|
|
217
|
+
}
|
|
218
|
+
else if (typeof expression.value === 'string') {
|
|
219
|
+
type = 'StringLiteral';
|
|
220
|
+
}
|
|
221
|
+
else if (typeof expression.value === 'number') {
|
|
222
|
+
type = 'NumericLiteral';
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
type = 'BooleanLiteral';
|
|
226
|
+
}
|
|
227
|
+
const loc = getSourceLocation(expression.start, expression.end, ctx);
|
|
228
|
+
const ex = expression.value === null
|
|
229
|
+
? { loc, type }
|
|
230
|
+
: {
|
|
231
|
+
loc,
|
|
232
|
+
type,
|
|
233
|
+
value: expression.value,
|
|
234
|
+
};
|
|
235
|
+
return {
|
|
236
|
+
ex,
|
|
237
|
+
kind: ValueType.CONST,
|
|
238
|
+
source: ctx.code.slice(expression.start, expression.end),
|
|
239
|
+
value: expression.value,
|
|
240
|
+
};
|
|
241
|
+
};
|
|
242
|
+
const extractExpression = (expression, ctx, evaluate) => {
|
|
243
|
+
const source = ctx.code.slice(expression.start, expression.end);
|
|
244
|
+
// Only inline function expressions are function-valued here. A bare
|
|
245
|
+
// identifier that points to a local function may be a styled runtime
|
|
246
|
+
// component, so it has to stay as a lazy `_exp()` reference.
|
|
247
|
+
const isFunction = expression.type === 'FunctionExpression' ||
|
|
248
|
+
expression.type === 'ArrowFunctionExpression';
|
|
249
|
+
if (evaluate) {
|
|
250
|
+
const evaluated = evaluateStatic(expression, ctx);
|
|
251
|
+
const literal = literalCode(evaluated);
|
|
252
|
+
if (literal) {
|
|
253
|
+
findReferences(expression, ctx.referencesByNode).forEach(({ name }) => ctx.dependencyNames.add(name));
|
|
254
|
+
return {
|
|
255
|
+
expressionCode: literal,
|
|
256
|
+
importedFrom: [],
|
|
257
|
+
kind: isFunction ? ValueType.FUNCTION : ValueType.LAZY,
|
|
258
|
+
staticImports: [],
|
|
259
|
+
staticValue: isStaticSerializableValue(evaluated)
|
|
260
|
+
? cloneStaticValue(evaluated)
|
|
261
|
+
: undefined,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
const identifierReplacements = new Map();
|
|
266
|
+
const importedFrom = [];
|
|
267
|
+
const namespaceStatic = collectStaticNamespaceMemberReferences(expression, ctx);
|
|
268
|
+
const staticIdentifierReplacements = new Map();
|
|
269
|
+
const staticImports = [
|
|
270
|
+
...namespaceStatic.imports,
|
|
271
|
+
];
|
|
272
|
+
let hasNonStaticLocalReference = false;
|
|
273
|
+
let hasInlinableLocalReference = false;
|
|
274
|
+
findReferences(expression, ctx.referencesByNode).forEach(({ name, start }) => {
|
|
275
|
+
const binding = resolveBindingAt(ctx, name, start);
|
|
276
|
+
if (!binding) {
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
if (isFunction && isBindingDeclaredWithin(binding, expression)) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
ctx.dependencyNames.add(name);
|
|
283
|
+
if (binding.importedFrom) {
|
|
284
|
+
importedFrom.push(binding.importedFrom);
|
|
285
|
+
if (binding.imported && binding.imported !== '*') {
|
|
286
|
+
staticImports.push({
|
|
287
|
+
imported: binding.imported,
|
|
288
|
+
local: binding.name,
|
|
289
|
+
source: binding.importedFrom,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
else if (binding.imported === '*' &&
|
|
293
|
+
namespaceStatic.coveredReferenceStarts.has(start)) {
|
|
294
|
+
// The static candidate source gets a synthetic named import alias,
|
|
295
|
+
// while the eval fallback keeps the original namespace expression.
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
hasNonStaticLocalReference = true;
|
|
299
|
+
}
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
const replacement = getConstantReplacement(binding, ctx);
|
|
303
|
+
if (evaluate && replacement) {
|
|
304
|
+
identifierReplacements.set(name, replacement);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
const init = binding.declarator?.init;
|
|
308
|
+
// Processor-managed bindings (`const x = css```, or object literals
|
|
309
|
+
// containing processor tags) carry values that only become known after
|
|
310
|
+
// processors run. Leave the identifier free in the candidate source so
|
|
311
|
+
// the resolver can supply it via inlineConstants at evaluation time.
|
|
312
|
+
const isProcessorManagedLocal = !!evaluate && !!init && containsTaggedTemplateExpression(init);
|
|
313
|
+
const staticLocalExpression = evaluate && init && !isProcessorManagedLocal
|
|
314
|
+
? collectStaticLocalExpression(init, ctx, [
|
|
315
|
+
hoistedBindingKey(binding),
|
|
316
|
+
])
|
|
317
|
+
: null;
|
|
318
|
+
if (staticLocalExpression) {
|
|
319
|
+
staticIdentifierReplacements.set(name, staticLocalExpression.source);
|
|
320
|
+
importedFrom.push(...staticLocalExpression.importedFrom);
|
|
321
|
+
staticImports.push(...staticLocalExpression.imports);
|
|
322
|
+
}
|
|
323
|
+
else if (isProcessorManagedLocal) {
|
|
324
|
+
hasInlinableLocalReference = true;
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
hasNonStaticLocalReference = true;
|
|
328
|
+
}
|
|
329
|
+
assertHoistable(binding, ctx);
|
|
330
|
+
addHoistedDeclaration(binding, ctx);
|
|
331
|
+
if (!binding.isRoot && binding.declarator?.id.type === 'Identifier') {
|
|
332
|
+
identifierReplacements.set(name, getHoistedBindingName(binding, ctx));
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
// Merge literal-const inlines (e.g. `const A = 32` -> "32") with
|
|
336
|
+
// local-to-imported substitutions (e.g. `const X = imp.y` -> "imp.y").
|
|
337
|
+
// Both must reach the candidate source so the resolver's evaluator
|
|
338
|
+
// can fold every Identifier in the expression; env only carries
|
|
339
|
+
// imported bindings, never same-file locals.
|
|
340
|
+
const mergedReplacements = new Map(staticIdentifierReplacements);
|
|
341
|
+
identifierReplacements.forEach((value, key) => {
|
|
342
|
+
if (!mergedReplacements.has(key)) {
|
|
343
|
+
mergedReplacements.set(key, value);
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
let staticExpressionCode;
|
|
347
|
+
if (mergedReplacements.size > 0) {
|
|
348
|
+
staticExpressionCode = replaceStaticLocalReferences(expression, mergedReplacements, ctx, namespaceStatic.replacements);
|
|
349
|
+
}
|
|
350
|
+
else if (namespaceStatic.replacements.length > 0) {
|
|
351
|
+
staticExpressionCode = applyExpressionReplacements(expression, namespaceStatic.replacements, ctx.code);
|
|
352
|
+
}
|
|
353
|
+
return {
|
|
354
|
+
expressionCode: identifierReplacements.size > 0
|
|
355
|
+
? replaceIdentifierReferences(expression, identifierReplacements, ctx.code)
|
|
356
|
+
: source,
|
|
357
|
+
importedFrom,
|
|
358
|
+
kind: isFunction ? ValueType.FUNCTION : ValueType.LAZY,
|
|
359
|
+
staticExpressionCode,
|
|
360
|
+
hasInlinableLocalReference: !hasNonStaticLocalReference && hasInlinableLocalReference,
|
|
361
|
+
staticImports: hasNonStaticLocalReference ? [] : staticImports,
|
|
362
|
+
};
|
|
363
|
+
};
|
|
364
|
+
const getInsertionPoints = (program, expressions) => {
|
|
365
|
+
if (expressions.length === 0) {
|
|
366
|
+
return [];
|
|
367
|
+
}
|
|
368
|
+
if (program.body.length === 0) {
|
|
369
|
+
return expressions.map(() => 0);
|
|
370
|
+
}
|
|
371
|
+
const insertionPoints = [];
|
|
372
|
+
let ownerIndex = 0;
|
|
373
|
+
expressions.forEach((expression) => {
|
|
374
|
+
while (ownerIndex < program.body.length - 1 &&
|
|
375
|
+
program.body[ownerIndex].end < expression.start) {
|
|
376
|
+
ownerIndex += 1;
|
|
377
|
+
}
|
|
378
|
+
let owner = program.body[ownerIndex];
|
|
379
|
+
if (!owner ||
|
|
380
|
+
owner.start > expression.start ||
|
|
381
|
+
owner.end < expression.end) {
|
|
382
|
+
owner = program.body.find((statement) => statement.start <= expression.start && statement.end >= expression.end);
|
|
383
|
+
}
|
|
384
|
+
insertionPoints.push(owner?.start ?? 0);
|
|
385
|
+
});
|
|
386
|
+
return insertionPoints;
|
|
387
|
+
};
|
|
388
|
+
const extractExpressions = (code, filename, evaluate, program, analysis, expressions, staticBindings) => {
|
|
389
|
+
if (expressions.length === 0) {
|
|
390
|
+
return {
|
|
391
|
+
code,
|
|
392
|
+
dependencyNames: [],
|
|
393
|
+
expressionValues: [],
|
|
394
|
+
staticValueCandidates: [],
|
|
395
|
+
staticValues: [],
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
const insertionPoints = getInsertionPoints(program, expressions);
|
|
399
|
+
const ctx = {
|
|
400
|
+
bindingResolutionCache: new Map(),
|
|
401
|
+
bindingsByName: analysis.bindingsByName,
|
|
402
|
+
code,
|
|
403
|
+
currentInsertionPoint: insertionPoints[0] ?? 0,
|
|
404
|
+
currentExpressionStart: expressions[0].start,
|
|
405
|
+
dependencyNames: new Set(),
|
|
406
|
+
expressionValues: [],
|
|
407
|
+
filename,
|
|
408
|
+
hoistedBindingNames: new Map(),
|
|
409
|
+
hoistedDeclarations: new Map(),
|
|
410
|
+
hoistedDeclarationsByInsertionPoint: new Map(),
|
|
411
|
+
loc: createOxcLocationLookup(code),
|
|
412
|
+
referencesByNode: new WeakMap(),
|
|
413
|
+
replacements: [],
|
|
414
|
+
rootMutationsByBinding: analysis.rootMutationsByBinding,
|
|
415
|
+
staticBindings,
|
|
416
|
+
staticImportAliases: new Map(),
|
|
417
|
+
staticValueCandidates: [],
|
|
418
|
+
staticValues: [],
|
|
419
|
+
usedNames: new Set(analysis.usedNames),
|
|
420
|
+
};
|
|
421
|
+
expressions.forEach((expression, index) => {
|
|
422
|
+
ctx.currentInsertionPoint = insertionPoints[index] ?? 0;
|
|
423
|
+
ctx.currentExpressionStart = expression.start;
|
|
424
|
+
const literal = literalExpressionValue(expression, ctx);
|
|
425
|
+
if (literal) {
|
|
426
|
+
ctx.expressionValues.push(literal);
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
const { expressionCode, hasInlinableLocalReference, importedFrom, kind, staticExpressionCode, staticImports, staticValue, } = extractExpression(expression, ctx, evaluate);
|
|
430
|
+
const expName = allocateExpressionName(ctx);
|
|
431
|
+
addHoistedCode(expName, `const ${expName} = () => (${expressionCode});`, ctx);
|
|
432
|
+
if (staticValue !== undefined && kind !== ValueType.FUNCTION) {
|
|
433
|
+
ctx.staticValues.push({
|
|
434
|
+
name: expName,
|
|
435
|
+
value: staticValue,
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
else if ((staticImports.length > 0 ||
|
|
439
|
+
hasInlinableLocalReference ||
|
|
440
|
+
staticExpressionCode !== undefined) &&
|
|
441
|
+
kind !== ValueType.FUNCTION) {
|
|
442
|
+
const uniqueImports = new Map();
|
|
443
|
+
staticImports.forEach((item) => {
|
|
444
|
+
uniqueImports.set(`${item.local}\0${item.importLocal ?? ''}\0${item.source}\0${item.imported}`, item);
|
|
445
|
+
});
|
|
446
|
+
ctx.staticValueCandidates.push({
|
|
447
|
+
imports: [...uniqueImports.values()],
|
|
448
|
+
name: expName,
|
|
449
|
+
source: staticExpressionCode ?? expressionCode,
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
ctx.replacements.push({
|
|
453
|
+
start: expression.start,
|
|
454
|
+
end: expression.end,
|
|
455
|
+
value: `${expName}()`,
|
|
456
|
+
});
|
|
457
|
+
ctx.expressionValues.push({
|
|
458
|
+
ex: {
|
|
459
|
+
loc: getSourceLocation(expression.start, expression.end, ctx),
|
|
460
|
+
name: expName,
|
|
461
|
+
type: 'Identifier',
|
|
462
|
+
},
|
|
463
|
+
importedFrom,
|
|
464
|
+
kind,
|
|
465
|
+
source: ctx.code.slice(expression.start, expression.end),
|
|
466
|
+
});
|
|
467
|
+
});
|
|
468
|
+
ctx.hoistedDeclarationsByInsertionPoint.forEach((declarations, point) => {
|
|
469
|
+
ctx.replacements.push({
|
|
470
|
+
start: point,
|
|
471
|
+
end: point,
|
|
472
|
+
value: `${declarations.join('\n')}\n`,
|
|
473
|
+
});
|
|
474
|
+
});
|
|
475
|
+
return {
|
|
476
|
+
code: applyOxcReplacements(code, ctx.replacements),
|
|
477
|
+
dependencyNames: [...ctx.dependencyNames],
|
|
478
|
+
expressionValues: ctx.expressionValues,
|
|
479
|
+
staticValueCandidates: ctx.staticValueCandidates,
|
|
480
|
+
staticValues: ctx.staticValues,
|
|
481
|
+
};
|
|
482
|
+
};
|
|
483
|
+
export const isOxcStaticSerializableValue = (value) => isStaticSerializableValue(value);
|
|
484
|
+
export const evaluateOxcStaticExpressionAt = (code, filename, expressionSpan, env = new Map(), staticBindings) => {
|
|
485
|
+
const program = parseOxc(code, filename);
|
|
486
|
+
const analysis = analyzeProgram(program, {
|
|
487
|
+
collectTargetExpressions: true,
|
|
488
|
+
expressionSpanLookup: createSpanLookup([expressionSpan]),
|
|
489
|
+
});
|
|
490
|
+
const [expression] = analysis.targetExpressions;
|
|
491
|
+
if (!expression) {
|
|
492
|
+
return undefined;
|
|
493
|
+
}
|
|
494
|
+
const ctx = {
|
|
495
|
+
bindingResolutionCache: new Map(),
|
|
496
|
+
bindingsByName: analysis.bindingsByName,
|
|
497
|
+
code,
|
|
498
|
+
currentInsertionPoint: 0,
|
|
499
|
+
currentExpressionStart: expression.start,
|
|
500
|
+
dependencyNames: new Set(),
|
|
501
|
+
expressionValues: [],
|
|
502
|
+
filename,
|
|
503
|
+
hoistedBindingNames: new Map(),
|
|
504
|
+
hoistedDeclarations: new Map(),
|
|
505
|
+
hoistedDeclarationsByInsertionPoint: new Map(),
|
|
506
|
+
loc: createOxcLocationLookup(code),
|
|
507
|
+
referencesByNode: new WeakMap(),
|
|
508
|
+
replacements: [],
|
|
509
|
+
rootMutationsByBinding: analysis.rootMutationsByBinding,
|
|
510
|
+
staticBindings,
|
|
511
|
+
staticImportAliases: new Map(),
|
|
512
|
+
staticValueCandidates: [],
|
|
513
|
+
staticValues: [],
|
|
514
|
+
usedNames: new Set(analysis.usedNames),
|
|
515
|
+
};
|
|
516
|
+
return evaluateStatic(expression, ctx, new Map(env));
|
|
517
|
+
};
|
|
518
|
+
export const evaluateOxcStaticExpression = (source, filename, env = new Map(), staticBindings) => {
|
|
519
|
+
const code = `const __wyw_static_value = ${source};`;
|
|
520
|
+
const program = parseOxc(code, filename);
|
|
521
|
+
const declaration = program.body[0];
|
|
522
|
+
if (declaration?.type !== 'VariableDeclaration') {
|
|
523
|
+
return undefined;
|
|
524
|
+
}
|
|
525
|
+
const [declarator] = declaration.declarations;
|
|
526
|
+
if (!declarator?.init) {
|
|
527
|
+
return undefined;
|
|
528
|
+
}
|
|
529
|
+
return evaluateOxcStaticExpressionAt(code, filename, {
|
|
530
|
+
end: declarator.init.end,
|
|
531
|
+
start: declarator.init.start,
|
|
532
|
+
}, env, staticBindings);
|
|
533
|
+
};
|
|
534
|
+
export const collectOxcExpressionDependencies = (code, filename, evaluate = false, targetExpressionSpans, staticBindings) => {
|
|
535
|
+
const program = parseOxc(code, filename);
|
|
536
|
+
const analysis = analyzeProgram(program, {
|
|
537
|
+
collectTargetExpressions: true,
|
|
538
|
+
expressionSpanLookup: createSpanLookup(targetExpressionSpans),
|
|
539
|
+
});
|
|
540
|
+
return extractExpressions(code, filename, evaluate, program, analysis, analysis.targetExpressions, staticBindings);
|
|
541
|
+
};
|
|
542
|
+
export const collectOxcTemplateDependencies = (code, filename, evaluate = false, targetTemplateSpans) => {
|
|
543
|
+
const program = parseOxc(code, filename);
|
|
544
|
+
const analysis = analyzeProgram(program, {
|
|
545
|
+
collectTemplateLiterals: true,
|
|
546
|
+
templateSpanLookup: createSpanLookup(targetTemplateSpans),
|
|
547
|
+
});
|
|
548
|
+
const expressions = analysis.templateLiterals.flatMap((template) => template.expressions);
|
|
549
|
+
return extractExpressions(code, filename, evaluate, program, analysis, expressions);
|
|
550
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Expression } from 'oxc-parser';
|
|
2
|
+
import type { Binding, ExtractionContext, OxcStaticImportReference, Replacement } from './types';
|
|
3
|
+
export declare const getConstantReplacement: (binding: Binding | undefined, ctx: ExtractionContext) => string | null;
|
|
4
|
+
export declare const collectIdentifierReferenceReplacements: (expression: Expression, replacements: Map<string, string>) => Replacement[];
|
|
5
|
+
export declare const applyExpressionReplacements: (expression: Expression, replacements: Replacement[], code: string) => string;
|
|
6
|
+
export declare const replaceIdentifierReferences: (expression: Expression, replacements: Map<string, string>, code: string) => string;
|
|
7
|
+
export declare const collectStaticNamespaceMemberReferences: (expression: Expression, ctx: ExtractionContext) => {
|
|
8
|
+
coveredReferenceStarts: Set<number>;
|
|
9
|
+
imports: OxcStaticImportReference[];
|
|
10
|
+
replacements: Replacement[];
|
|
11
|
+
};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/* eslint-disable no-restricted-syntax */
|
|
2
|
+
import { getOxcNodeChildren } from '../oxc/ast';
|
|
3
|
+
import { isBindingPosition, isInTypeContext, isObjectPropertyKey, isPropertyOnlyIdentifier, resolveBindingAt, } from './scopeAnalysis';
|
|
4
|
+
import { evaluateStatic, literalCode } from './staticEvaluator';
|
|
5
|
+
export const getConstantReplacement = (binding, ctx) => {
|
|
6
|
+
const init = binding?.declarator?.init;
|
|
7
|
+
if (!init) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
if (init.type === 'Literal') {
|
|
11
|
+
return literalCode(init.value);
|
|
12
|
+
}
|
|
13
|
+
if (init.type === 'ObjectExpression' &&
|
|
14
|
+
binding?.isRoot &&
|
|
15
|
+
binding.declarator?.id.type === 'Identifier') {
|
|
16
|
+
const evaluated = evaluateStatic(binding.declarator.id, ctx);
|
|
17
|
+
return literalCode(evaluated);
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
};
|
|
21
|
+
export const collectIdentifierReferenceReplacements = (expression, replacements) => {
|
|
22
|
+
const localReplacements = [];
|
|
23
|
+
const ancestors = [];
|
|
24
|
+
const walk = (current, parent) => {
|
|
25
|
+
if (current.type === 'Identifier' &&
|
|
26
|
+
replacements.has(current.name) &&
|
|
27
|
+
!isInTypeContext(ancestors) &&
|
|
28
|
+
!isBindingPosition(current, parent) &&
|
|
29
|
+
!isPropertyOnlyIdentifier(current, parent) &&
|
|
30
|
+
!isObjectPropertyKey(current, parent)) {
|
|
31
|
+
const replacement = replacements.get(current.name);
|
|
32
|
+
// Shorthand property `{ width }` → `{ width: 500 }` when the
|
|
33
|
+
// identifier is the value side of a shorthand ObjectProperty.
|
|
34
|
+
const isShorthandValue = !!parent &&
|
|
35
|
+
parent.type === 'Property' &&
|
|
36
|
+
parent.shorthand &&
|
|
37
|
+
parent.value === current;
|
|
38
|
+
localReplacements.push({
|
|
39
|
+
start: isShorthandValue ? parent.start : current.start,
|
|
40
|
+
end: current.end,
|
|
41
|
+
value: isShorthandValue
|
|
42
|
+
? `${current.name}: ${replacement}`
|
|
43
|
+
: replacement,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
ancestors.push(current);
|
|
47
|
+
getOxcNodeChildren(current).forEach((child) => walk(child, current));
|
|
48
|
+
ancestors.pop();
|
|
49
|
+
};
|
|
50
|
+
walk(expression, null);
|
|
51
|
+
return localReplacements;
|
|
52
|
+
};
|
|
53
|
+
export const applyExpressionReplacements = (expression, replacements, code) => {
|
|
54
|
+
let result = code.slice(expression.start, expression.end);
|
|
55
|
+
replacements
|
|
56
|
+
.sort((a, b) => b.start - a.start)
|
|
57
|
+
.forEach((replacement) => {
|
|
58
|
+
const start = replacement.start - expression.start;
|
|
59
|
+
const end = replacement.end - expression.start;
|
|
60
|
+
result = result.slice(0, start) + replacement.value + result.slice(end);
|
|
61
|
+
});
|
|
62
|
+
return result;
|
|
63
|
+
};
|
|
64
|
+
export const replaceIdentifierReferences = (expression, replacements, code) => {
|
|
65
|
+
return applyExpressionReplacements(expression, collectIdentifierReferenceReplacements(expression, replacements), code);
|
|
66
|
+
};
|
|
67
|
+
const staticImportAliasPart = (value) => value.replace(/[^A-Za-z0-9_$]/g, '_') || 'value';
|
|
68
|
+
const allocateStaticImportAlias = (binding, imported, ctx) => {
|
|
69
|
+
const key = `${binding.importedFrom ?? ''}\0${binding.name}\0${imported}`;
|
|
70
|
+
const existing = ctx.staticImportAliases.get(key);
|
|
71
|
+
if (existing) {
|
|
72
|
+
return existing;
|
|
73
|
+
}
|
|
74
|
+
const namespacePart = staticImportAliasPart(binding.name);
|
|
75
|
+
const importedPart = staticImportAliasPart(imported);
|
|
76
|
+
let alias = `_wyw_static_${namespacePart}_${importedPart}`;
|
|
77
|
+
let idx = 1;
|
|
78
|
+
while (ctx.usedNames.has(alias)) {
|
|
79
|
+
idx += 1;
|
|
80
|
+
alias = `_wyw_static_${namespacePart}_${importedPart}_${idx}`;
|
|
81
|
+
}
|
|
82
|
+
ctx.usedNames.add(alias);
|
|
83
|
+
ctx.staticImportAliases.set(key, alias);
|
|
84
|
+
return alias;
|
|
85
|
+
};
|
|
86
|
+
const staticMemberPropertyName = (expression) => {
|
|
87
|
+
if (!expression.computed && expression.property.type === 'Identifier') {
|
|
88
|
+
return expression.property.name;
|
|
89
|
+
}
|
|
90
|
+
if (expression.computed &&
|
|
91
|
+
expression.property.type === 'Literal' &&
|
|
92
|
+
typeof expression.property.value === 'string') {
|
|
93
|
+
return expression.property.value;
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
};
|
|
97
|
+
export const collectStaticNamespaceMemberReferences = (expression, ctx) => {
|
|
98
|
+
const coveredReferenceStarts = new Set();
|
|
99
|
+
const imports = new Map();
|
|
100
|
+
const replacements = [];
|
|
101
|
+
const walk = (node) => {
|
|
102
|
+
if (node.type === 'MemberExpression' && node.object.type === 'Identifier') {
|
|
103
|
+
const binding = resolveBindingAt(ctx, node.object.name, node.object.start);
|
|
104
|
+
const imported = staticMemberPropertyName(node);
|
|
105
|
+
if (binding?.importedFrom &&
|
|
106
|
+
binding.imported === '*' &&
|
|
107
|
+
imported !== null) {
|
|
108
|
+
const alias = allocateStaticImportAlias(binding, imported, ctx);
|
|
109
|
+
imports.set(`${binding.importedFrom}\0${imported}\0${alias}`, {
|
|
110
|
+
imported,
|
|
111
|
+
importLocal: binding.name,
|
|
112
|
+
local: alias,
|
|
113
|
+
source: binding.importedFrom,
|
|
114
|
+
});
|
|
115
|
+
replacements.push({
|
|
116
|
+
end: node.end,
|
|
117
|
+
start: node.start,
|
|
118
|
+
value: alias,
|
|
119
|
+
});
|
|
120
|
+
coveredReferenceStarts.add(node.object.start);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
getOxcNodeChildren(node).forEach(walk);
|
|
124
|
+
};
|
|
125
|
+
walk(expression);
|
|
126
|
+
return {
|
|
127
|
+
coveredReferenceStarts,
|
|
128
|
+
imports: [...imports.values()],
|
|
129
|
+
replacements,
|
|
130
|
+
};
|
|
131
|
+
};
|