@wyw-in-js/transform 2.0.0-alpha.1 → 2.0.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.
Files changed (44) hide show
  1. package/esm/transform/Entrypoint.types.js.map +1 -1
  2. package/esm/transform/generators/collect.js +1 -0
  3. package/esm/transform/generators/collect.js.map +1 -1
  4. package/esm/transform/generators/resolveStaticOxcValues/prune.js +91 -5
  5. package/esm/transform/generators/resolveStaticOxcValues/prune.js.map +1 -1
  6. package/esm/transform/generators/resolveStaticOxcValues/resolveStaticOxcPreevalValues.js +2 -1
  7. package/esm/transform/generators/resolveStaticOxcValues/resolveStaticOxcPreevalValues.js.map +1 -1
  8. package/esm/transform/generators/transform.js +1 -0
  9. package/esm/transform/generators/transform.js.map +1 -1
  10. package/esm/utils/EventEmitter.js +13 -0
  11. package/esm/utils/EventEmitter.js.map +1 -1
  12. package/esm/utils/applyOxcProcessors/applyOxcProcessors.js +1 -1
  13. package/esm/utils/applyOxcProcessors/applyOxcProcessors.js.map +1 -1
  14. package/esm/utils/applyOxcProcessors/cleanupRemovals.js +102 -16
  15. package/esm/utils/applyOxcProcessors/cleanupRemovals.js.map +1 -1
  16. package/esm/utils/collectOxcExportsAndImports.js +8 -0
  17. package/esm/utils/collectOxcExportsAndImports.js.map +1 -1
  18. package/esm/utils/collectOxcRuntime/types.js.map +1 -1
  19. package/esm/utils/collectOxcTemplateDependencies/expressionExtraction.js +6 -4
  20. package/esm/utils/collectOxcTemplateDependencies/expressionExtraction.js.map +1 -1
  21. package/esm/utils/oxc/ast.js +42 -12
  22. package/esm/utils/oxc/ast.js.map +1 -1
  23. package/esm/utils/oxcPreevalTransforms.js +94 -65
  24. package/esm/utils/oxcPreevalTransforms.js.map +1 -1
  25. package/esm/utils/parseOxc.js +6 -1
  26. package/esm/utils/parseOxc.js.map +1 -1
  27. package/package.json +5 -5
  28. package/types/transform/Entrypoint.types.d.ts +1 -0
  29. package/types/transform/generators/collect.js +1 -0
  30. package/types/transform/generators/resolveStaticOxcValues/prune.d.ts +1 -1
  31. package/types/transform/generators/resolveStaticOxcValues/prune.js +96 -4
  32. package/types/transform/generators/resolveStaticOxcValues/resolveStaticOxcPreevalValues.js +2 -1
  33. package/types/transform/generators/transform.js +1 -0
  34. package/types/utils/EventEmitter.js +13 -0
  35. package/types/utils/applyOxcProcessors/applyOxcProcessors.d.ts +1 -0
  36. package/types/utils/applyOxcProcessors/applyOxcProcessors.js +3 -1
  37. package/types/utils/applyOxcProcessors/cleanupRemovals.d.ts +2 -2
  38. package/types/utils/applyOxcProcessors/cleanupRemovals.js +104 -19
  39. package/types/utils/collectOxcExportsAndImports.js +8 -0
  40. package/types/utils/collectOxcRuntime/types.d.ts +1 -0
  41. package/types/utils/collectOxcTemplateDependencies/expressionExtraction.js +6 -4
  42. package/types/utils/oxc/ast.js +42 -18
  43. package/types/utils/oxcPreevalTransforms.js +97 -74
  44. package/types/utils/parseOxc.js +6 -1
@@ -281,10 +281,12 @@ const extractExpression = (expression, ctx, evaluate) => {
281
281
  } else {
282
282
  hasNonStaticLocalReference = true;
283
283
  }
284
- assertHoistable(binding, ctx);
285
- addHoistedDeclaration(binding, ctx);
286
- if (!binding.isRoot && binding.declarator?.id.type === "Identifier") {
287
- identifierReplacements.set(name, getHoistedBindingName(binding, ctx));
284
+ if (!isProcessorManagedLocal) {
285
+ assertHoistable(binding, ctx);
286
+ addHoistedDeclaration(binding, ctx);
287
+ if (!binding.isRoot && binding.declarator?.id.type === "Identifier") {
288
+ identifierReplacements.set(name, getHoistedBindingName(binding, ctx));
289
+ }
288
290
  }
289
291
  });
290
292
  // Merge literal-const inlines (e.g. `const A = 32` -> "32") with
@@ -1 +1 @@
1
- {"mappings":"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","names":[],"sources":["../../../src/utils/collectOxcTemplateDependencies/expressionExtraction.ts"],"version":3,"sourcesContent":["/* eslint-disable no-restricted-syntax,no-continue */\n\nimport type { ExpressionValue } from '@wyw-in-js/shared';\nimport { ValueType } from '@wyw-in-js/shared';\nimport type { Expression, Program } from 'oxc-parser';\n\nimport { applyOxcReplacements } from '../oxc/replacements';\nimport { createOxcLocationLookup } from '../oxc/sourceLocations';\nimport {\n analyzeProgram,\n containsTaggedTemplateExpression,\n createSpanLookup,\n findReferences,\n getSourceLocation,\n isBindingDeclaredWithin,\n parseOxc,\n resolveBindingAt,\n} from './scopeAnalysis';\nimport {\n applyExpressionReplacements,\n collectIdentifierReferenceReplacements,\n collectStaticNamespaceMemberReferences,\n getConstantReplacement,\n replaceIdentifierReferences,\n} from './expressionReplacements';\nimport {\n cloneStaticValue,\n evaluateStatic,\n isStaticSerializableValue,\n literalCode,\n} from './staticEvaluator';\nimport type {\n Binding,\n ExtractedExpression,\n ExpressionSpan,\n ExtractionContext,\n OxcStaticImportReference,\n ProgramAnalysis,\n Replacement,\n StaticBindings,\n StaticLocalExpression,\n TemplateExtractionResult,\n} from './types';\n\nconst allocateExpressionName = (ctx: ExtractionContext): string => {\n let base = '_exp';\n let idx = 1;\n while (ctx.usedNames.has(base)) {\n idx += 1;\n base = `_exp${idx}`;\n }\n\n ctx.usedNames.add(base);\n return base;\n};\n\nconst hoistedBindingKey = (binding: Binding): string =>\n `${binding.scope.start}:${binding.scope.end}:${binding.declaredAt}:${binding.name}`;\n\nconst allocateHoistedBindingName = (\n originalName: string,\n ctx: ExtractionContext\n): string => {\n const sanitized = originalName.replace(/[^A-Za-z0-9_$]/g, '_') || 'hoisted';\n const base = /^[A-Za-z_$]/.test(sanitized) ? `_${sanitized}` : '_hoisted';\n let candidate = base;\n let idx = 2;\n\n while (ctx.usedNames.has(candidate)) {\n candidate = `${base}${idx}`;\n idx += 1;\n }\n\n ctx.usedNames.add(candidate);\n return candidate;\n};\n\nconst getHoistedBindingName = (\n binding: Binding,\n ctx: ExtractionContext\n): string => {\n const key = hoistedBindingKey(binding);\n const existing = ctx.hoistedBindingNames.get(key);\n if (existing) {\n return existing;\n }\n\n const next = allocateHoistedBindingName(binding.name, ctx);\n ctx.hoistedBindingNames.set(key, next);\n return next;\n};\n\nconst parenthesizeStaticReplacement = (source: string): string => `(${source})`;\n\nconst replaceStaticLocalReferences = (\n expression: Expression,\n replacements: Map<string, string>,\n ctx: ExtractionContext,\n extraReplacements: Replacement[] = []\n): string => {\n if (expression.type === 'Identifier' && extraReplacements.length === 0) {\n return (\n replacements.get(expression.name) ??\n ctx.code.slice(expression.start, expression.end)\n );\n }\n\n const parenthesized = new Map<string, string>();\n replacements.forEach((value, key) => {\n parenthesized.set(key, parenthesizeStaticReplacement(value));\n });\n\n return applyExpressionReplacements(\n expression,\n [\n ...extraReplacements,\n ...collectIdentifierReferenceReplacements(expression, parenthesized),\n ],\n ctx.code\n );\n};\n\nconst collectStaticLocalExpression = (\n expression: Expression,\n ctx: ExtractionContext,\n stack: string[] = []\n): StaticLocalExpression | null => {\n const replacements = new Map<string, string>();\n const importedFrom = new Set<string>();\n const imports: OxcStaticImportReference[] = [];\n\n for (const { name, start } of findReferences(\n expression,\n ctx.referencesByNode\n )) {\n const binding = resolveBindingAt(ctx, name, start);\n if (!binding) {\n return null;\n }\n\n if (binding.importedFrom) {\n importedFrom.add(binding.importedFrom);\n if (binding.imported && binding.imported !== '*') {\n imports.push({\n imported: binding.imported,\n local: binding.name,\n source: binding.importedFrom,\n });\n continue;\n }\n\n return null;\n }\n\n const replacement = getConstantReplacement(binding, ctx);\n if (replacement) {\n replacements.set(name, replacement);\n continue;\n }\n\n if (\n binding.kind === 'param' ||\n binding.declarationKind !== 'const' ||\n !binding.declarator?.init ||\n binding.declarator.id.type !== 'Identifier'\n ) {\n return null;\n }\n\n // Processor-managed bindings (const x = css``) carry their value\n // (the generated className string) via inlineConstants at candidate\n // evaluation time. Walking the TaggedTemplateExpression here would\n // pull the processor's tag import (e.g. `css` from '@linaria/core')\n // into the candidate's static imports, where it fails to resolve.\n // Leave the identifier as a free reference; the candidate-side env\n // supplies the className.\n if (binding.declarator.init.type === 'TaggedTemplateExpression') {\n continue;\n }\n\n const key = hoistedBindingKey(binding);\n if (stack.includes(key)) {\n return null;\n }\n\n const nested = collectStaticLocalExpression(binding.declarator.init, ctx, [\n ...stack,\n key,\n ]);\n if (!nested) {\n return null;\n }\n\n replacements.set(name, nested.source);\n nested.importedFrom.forEach((source) => importedFrom.add(source));\n imports.push(...nested.imports);\n }\n\n return {\n importedFrom: [...importedFrom],\n imports,\n source:\n replacements.size > 0\n ? replaceStaticLocalReferences(expression, replacements, ctx)\n : ctx.code.slice(expression.start, expression.end),\n };\n};\n\nconst declarationInitCode = (\n init: Expression,\n ctx: ExtractionContext\n): string => {\n const renamedDependencies = new Map<string, string>();\n findReferences(init, ctx.referencesByNode).forEach(({ name, start }) => {\n const dependency = resolveBindingAt(ctx, name, start);\n if (\n !dependency ||\n dependency.importedFrom ||\n dependency.isRoot ||\n dependency.declarator?.id.type !== 'Identifier'\n ) {\n return;\n }\n\n renamedDependencies.set(name, getHoistedBindingName(dependency, ctx));\n });\n\n return renamedDependencies.size > 0\n ? replaceIdentifierReferences(init, renamedDependencies, ctx.code)\n : ctx.code.slice(init.start, init.end);\n};\n\nconst addHoistedCode = (\n key: string,\n code: string,\n ctx: ExtractionContext\n): void => {\n if (ctx.hoistedDeclarations.has(key)) {\n return;\n }\n\n ctx.hoistedDeclarations.set(key, code);\n const declarations =\n ctx.hoistedDeclarationsByInsertionPoint.get(ctx.currentInsertionPoint) ??\n [];\n declarations.push(code);\n ctx.hoistedDeclarationsByInsertionPoint.set(\n ctx.currentInsertionPoint,\n declarations\n );\n};\n\nconst declarationCode = (binding: Binding, ctx: ExtractionContext): string => {\n const { declarator } = binding;\n if (!declarator) {\n return '';\n }\n\n const { id } = declarator;\n if (id.type !== 'Identifier') {\n const idCode = ctx.code.slice(id.start, id.end);\n if (!declarator.init) {\n return `let ${idCode};`;\n }\n\n return `let ${idCode} = ${declarationInitCode(declarator.init, ctx)};`;\n }\n\n const hoistedName = getHoistedBindingName(binding, ctx);\n if (!declarator.init) {\n return `let ${hoistedName};`;\n }\n\n return `let ${hoistedName} = ${declarationInitCode(declarator.init, ctx)};`;\n};\n\nconst assertHoistable = (\n binding: Binding,\n ctx: ExtractionContext,\n stack: string[] = []\n): void => {\n if (!binding.declarator?.init || binding.importedFrom || binding.isRoot) {\n return;\n }\n\n if (stack.includes(binding.name)) {\n return;\n }\n\n const refs = findReferences(binding.declarator.init, ctx.referencesByNode);\n refs.forEach(({ name, start }) => {\n const nextBinding = resolveBindingAt(ctx, name, start);\n if (!nextBinding) {\n return;\n }\n\n if (nextBinding.kind === 'param') {\n throw new Error(\n `This identifier cannot be used in the template, because it is a function parameter.`\n );\n }\n\n assertHoistable(nextBinding, ctx, [...stack, binding.name]);\n });\n};\n\nconst addHoistedDeclaration = (\n binding: Binding,\n ctx: ExtractionContext,\n stack: string[] = []\n): void => {\n if (\n !binding.declaration ||\n !binding.declarator ||\n binding.importedFrom ||\n binding.isRoot ||\n stack.includes(binding.name)\n ) {\n return;\n }\n\n const hoistSource = binding.declarator.init ?? binding.declarator;\n findReferences(hoistSource, ctx.referencesByNode).forEach(\n ({ name, start }) => {\n const dependency = resolveBindingAt(ctx, name, start);\n if (dependency) {\n addHoistedDeclaration(dependency, ctx, [...stack, binding.name]);\n }\n }\n );\n\n if (!ctx.hoistedDeclarations.has(binding.name)) {\n addHoistedCode(binding.name, declarationCode(binding, ctx), ctx);\n }\n};\n\nconst literalExpressionValue = (\n expression: Expression,\n ctx: ExtractionContext\n): Omit<ExpressionValue, 'buildCodeFrameError'> | null => {\n if (expression.type !== 'Literal') {\n return null;\n }\n\n if (\n expression.value !== null &&\n typeof expression.value !== 'string' &&\n typeof expression.value !== 'number' &&\n typeof expression.value !== 'boolean'\n ) {\n return null;\n }\n\n let type:\n | 'BooleanLiteral'\n | 'NullLiteral'\n | 'NumericLiteral'\n | 'StringLiteral';\n if (expression.value === null) {\n type = 'NullLiteral';\n } else if (typeof expression.value === 'string') {\n type = 'StringLiteral';\n } else if (typeof expression.value === 'number') {\n type = 'NumericLiteral';\n } else {\n type = 'BooleanLiteral';\n }\n\n const loc = getSourceLocation(expression.start, expression.end, ctx);\n const ex =\n expression.value === null\n ? { loc, type }\n : {\n loc,\n type,\n value: expression.value,\n };\n\n return {\n ex,\n kind: ValueType.CONST,\n source: ctx.code.slice(expression.start, expression.end),\n value: expression.value,\n } as unknown as Omit<ExpressionValue, 'buildCodeFrameError'>;\n};\n\nconst extractExpression = (\n expression: Expression,\n ctx: ExtractionContext,\n evaluate: boolean\n): ExtractedExpression => {\n const source = ctx.code.slice(expression.start, expression.end);\n // Only inline function expressions are function-valued here. A bare\n // identifier that points to a local function may be a styled runtime\n // component, so it has to stay as a lazy `_exp()` reference.\n const isFunction =\n expression.type === 'FunctionExpression' ||\n expression.type === 'ArrowFunctionExpression';\n\n if (evaluate) {\n const evaluated = evaluateStatic(expression, ctx);\n const literal = literalCode(evaluated);\n if (literal) {\n findReferences(expression, ctx.referencesByNode).forEach(({ name }) =>\n ctx.dependencyNames.add(name)\n );\n return {\n expressionCode: literal,\n importedFrom: [],\n kind: isFunction ? ValueType.FUNCTION : ValueType.LAZY,\n staticImports: [],\n staticValue: isStaticSerializableValue(evaluated)\n ? cloneStaticValue(evaluated)\n : undefined,\n };\n }\n }\n\n const identifierReplacements = new Map<string, string>();\n const importedFrom: string[] = [];\n const namespaceStatic = collectStaticNamespaceMemberReferences(\n expression,\n ctx\n );\n const staticIdentifierReplacements = new Map<string, string>();\n const staticImports: OxcStaticImportReference[] = [\n ...namespaceStatic.imports,\n ];\n let hasNonStaticLocalReference = false;\n let hasInlinableLocalReference = false;\n\n findReferences(expression, ctx.referencesByNode).forEach(\n ({ name, start }) => {\n const binding = resolveBindingAt(ctx, name, start);\n if (!binding) {\n return;\n }\n\n if (isFunction && isBindingDeclaredWithin(binding, expression)) {\n return;\n }\n\n ctx.dependencyNames.add(name);\n\n if (binding.importedFrom) {\n importedFrom.push(binding.importedFrom);\n if (binding.imported && binding.imported !== '*') {\n staticImports.push({\n imported: binding.imported,\n local: binding.name,\n source: binding.importedFrom,\n });\n } else if (\n binding.imported === '*' &&\n namespaceStatic.coveredReferenceStarts.has(start)\n ) {\n // The static candidate source gets a synthetic named import alias,\n // while the eval fallback keeps the original namespace expression.\n } else {\n hasNonStaticLocalReference = true;\n }\n return;\n }\n\n const replacement = getConstantReplacement(binding, ctx);\n if (evaluate && replacement) {\n identifierReplacements.set(name, replacement);\n return;\n }\n\n const init = binding.declarator?.init;\n // Processor-managed bindings (`const x = css```, or object literals\n // containing processor tags) carry values that only become known after\n // processors run. Leave the identifier free in the candidate source so\n // the resolver can supply it via inlineConstants at evaluation time.\n const isProcessorManagedLocal =\n !!evaluate && !!init && containsTaggedTemplateExpression(init);\n const staticLocalExpression =\n evaluate && init && !isProcessorManagedLocal\n ? collectStaticLocalExpression(init, ctx, [\n hoistedBindingKey(binding),\n ])\n : null;\n if (staticLocalExpression) {\n staticIdentifierReplacements.set(name, staticLocalExpression.source);\n importedFrom.push(...staticLocalExpression.importedFrom);\n staticImports.push(...staticLocalExpression.imports);\n } else if (isProcessorManagedLocal) {\n hasInlinableLocalReference = true;\n } else {\n hasNonStaticLocalReference = true;\n }\n\n assertHoistable(binding, ctx);\n addHoistedDeclaration(binding, ctx);\n if (!binding.isRoot && binding.declarator?.id.type === 'Identifier') {\n identifierReplacements.set(name, getHoistedBindingName(binding, ctx));\n }\n }\n );\n\n // Merge literal-const inlines (e.g. `const A = 32` -> \"32\") with\n // local-to-imported substitutions (e.g. `const X = imp.y` -> \"imp.y\").\n // Both must reach the candidate source so the resolver's evaluator\n // can fold every Identifier in the expression; env only carries\n // imported bindings, never same-file locals.\n const mergedReplacements = new Map(staticIdentifierReplacements);\n identifierReplacements.forEach((value, key) => {\n if (!mergedReplacements.has(key)) {\n mergedReplacements.set(key, value);\n }\n });\n\n let staticExpressionCode: string | undefined;\n if (mergedReplacements.size > 0) {\n staticExpressionCode = replaceStaticLocalReferences(\n expression,\n mergedReplacements,\n ctx,\n namespaceStatic.replacements\n );\n } else if (namespaceStatic.replacements.length > 0) {\n staticExpressionCode = applyExpressionReplacements(\n expression,\n namespaceStatic.replacements,\n ctx.code\n );\n }\n\n return {\n expressionCode:\n identifierReplacements.size > 0\n ? replaceIdentifierReferences(\n expression,\n identifierReplacements,\n ctx.code\n )\n : source,\n importedFrom,\n kind: isFunction ? ValueType.FUNCTION : ValueType.LAZY,\n staticExpressionCode,\n hasInlinableLocalReference:\n !hasNonStaticLocalReference && hasInlinableLocalReference,\n staticImports: hasNonStaticLocalReference ? [] : staticImports,\n };\n};\n\nconst getInsertionPoints = (\n program: Program,\n expressions: Expression[]\n): number[] => {\n if (expressions.length === 0) {\n return [];\n }\n\n if (program.body.length === 0) {\n return expressions.map(() => 0);\n }\n\n const insertionPoints: number[] = [];\n let ownerIndex = 0;\n\n expressions.forEach((expression) => {\n while (\n ownerIndex < program.body.length - 1 &&\n program.body[ownerIndex]!.end < expression.start\n ) {\n ownerIndex += 1;\n }\n\n let owner: Program['body'][number] | undefined = program.body[ownerIndex];\n if (\n !owner ||\n owner.start > expression.start ||\n owner.end < expression.end\n ) {\n owner = program.body.find(\n (statement) =>\n statement.start <= expression.start && statement.end >= expression.end\n );\n }\n\n insertionPoints.push(owner?.start ?? 0);\n });\n\n return insertionPoints;\n};\n\nconst extractExpressions = (\n code: string,\n filename: string,\n evaluate: boolean,\n program: Program,\n analysis: Pick<\n ProgramAnalysis,\n 'bindingsByName' | 'rootMutationsByBinding' | 'usedNames'\n >,\n expressions: Expression[],\n staticBindings?: StaticBindings\n): TemplateExtractionResult => {\n if (expressions.length === 0) {\n return {\n code,\n dependencyNames: [],\n expressionValues: [],\n staticValueCandidates: [],\n staticValues: [],\n };\n }\n\n const insertionPoints = getInsertionPoints(program, expressions);\n const ctx: ExtractionContext = {\n bindingResolutionCache: new Map(),\n bindingsByName: analysis.bindingsByName,\n code,\n currentInsertionPoint: insertionPoints[0] ?? 0,\n currentExpressionStart: expressions[0].start,\n dependencyNames: new Set(),\n expressionValues: [],\n filename,\n hoistedBindingNames: new Map(),\n hoistedDeclarations: new Map(),\n hoistedDeclarationsByInsertionPoint: new Map(),\n loc: createOxcLocationLookup(code),\n referencesByNode: new WeakMap(),\n replacements: [],\n rootMutationsByBinding: analysis.rootMutationsByBinding,\n staticBindings,\n staticImportAliases: new Map(),\n staticValueCandidates: [],\n staticValues: [],\n usedNames: new Set(analysis.usedNames),\n };\n\n expressions.forEach((expression, index) => {\n ctx.currentInsertionPoint = insertionPoints[index] ?? 0;\n ctx.currentExpressionStart = expression.start;\n\n const literal = literalExpressionValue(expression, ctx);\n if (literal) {\n ctx.expressionValues.push(literal);\n return;\n }\n\n const {\n expressionCode,\n hasInlinableLocalReference,\n importedFrom,\n kind,\n staticExpressionCode,\n staticImports,\n staticValue,\n } = extractExpression(expression, ctx, evaluate);\n const expName = allocateExpressionName(ctx);\n\n addHoistedCode(\n expName,\n `const ${expName} = () => (${expressionCode});`,\n ctx\n );\n if (staticValue !== undefined && kind !== ValueType.FUNCTION) {\n ctx.staticValues.push({\n name: expName,\n value: staticValue,\n });\n } else if (\n (staticImports.length > 0 ||\n hasInlinableLocalReference ||\n staticExpressionCode !== undefined) &&\n kind !== ValueType.FUNCTION\n ) {\n const uniqueImports = new Map<string, OxcStaticImportReference>();\n staticImports.forEach((item) => {\n uniqueImports.set(\n `${item.local}\\0${item.importLocal ?? ''}\\0${item.source}\\0${\n item.imported\n }`,\n item\n );\n });\n ctx.staticValueCandidates.push({\n imports: [...uniqueImports.values()],\n name: expName,\n source: staticExpressionCode ?? expressionCode,\n });\n }\n ctx.replacements.push({\n start: expression.start,\n end: expression.end,\n value: `${expName}()`,\n });\n ctx.expressionValues.push({\n ex: {\n loc: getSourceLocation(expression.start, expression.end, ctx),\n name: expName,\n type: 'Identifier',\n },\n importedFrom,\n kind,\n source: ctx.code.slice(expression.start, expression.end),\n } as unknown as Omit<ExpressionValue, 'buildCodeFrameError'>);\n });\n\n ctx.hoistedDeclarationsByInsertionPoint.forEach((declarations, point) => {\n ctx.replacements.push({\n start: point,\n end: point,\n value: `${declarations.join('\\n')}\\n`,\n });\n });\n\n return {\n code: applyOxcReplacements(code, ctx.replacements),\n dependencyNames: [...ctx.dependencyNames],\n expressionValues: ctx.expressionValues,\n staticValueCandidates: ctx.staticValueCandidates,\n staticValues: ctx.staticValues,\n };\n};\n\nexport const isOxcStaticSerializableValue = (value: unknown): boolean =>\n isStaticSerializableValue(value);\n\nexport const evaluateOxcStaticExpressionAt = (\n code: string,\n filename: string,\n expressionSpan: ExpressionSpan,\n env: Map<string, unknown> = new Map(),\n staticBindings?: StaticBindings\n): unknown | undefined => {\n const program = parseOxc(code, filename);\n const analysis = analyzeProgram(program, {\n collectTargetExpressions: true,\n expressionSpanLookup: createSpanLookup([expressionSpan]),\n });\n const [expression] = analysis.targetExpressions;\n if (!expression) {\n return undefined;\n }\n\n const ctx: ExtractionContext = {\n bindingResolutionCache: new Map(),\n bindingsByName: analysis.bindingsByName,\n code,\n currentInsertionPoint: 0,\n currentExpressionStart: expression.start,\n dependencyNames: new Set(),\n expressionValues: [],\n filename,\n hoistedBindingNames: new Map(),\n hoistedDeclarations: new Map(),\n hoistedDeclarationsByInsertionPoint: new Map(),\n loc: createOxcLocationLookup(code),\n referencesByNode: new WeakMap(),\n replacements: [],\n rootMutationsByBinding: analysis.rootMutationsByBinding,\n staticBindings,\n staticImportAliases: new Map(),\n staticValueCandidates: [],\n staticValues: [],\n usedNames: new Set(analysis.usedNames),\n };\n\n return evaluateStatic(expression, ctx, new Map(env));\n};\n\nexport const evaluateOxcStaticExpression = (\n source: string,\n filename: string,\n env: Map<string, unknown> = new Map(),\n staticBindings?: StaticBindings\n): unknown | undefined => {\n const code = `const __wyw_static_value = ${source};`;\n const program = parseOxc(code, filename);\n const declaration = program.body[0];\n if (declaration?.type !== 'VariableDeclaration') {\n return undefined;\n }\n\n const [declarator] = declaration.declarations;\n if (!declarator?.init) {\n return undefined;\n }\n\n return evaluateOxcStaticExpressionAt(\n code,\n filename,\n {\n end: declarator.init.end,\n start: declarator.init.start,\n },\n env,\n staticBindings\n );\n};\n\nexport const collectOxcExpressionDependencies = (\n code: string,\n filename: string,\n evaluate = false,\n targetExpressionSpans?: ExpressionSpan[],\n staticBindings?: StaticBindings\n): TemplateExtractionResult => {\n const program = parseOxc(code, filename);\n const analysis = analyzeProgram(program, {\n collectTargetExpressions: true,\n expressionSpanLookup: createSpanLookup(targetExpressionSpans),\n });\n\n return extractExpressions(\n code,\n filename,\n evaluate,\n program,\n analysis,\n analysis.targetExpressions,\n staticBindings\n );\n};\n\nexport const collectOxcTemplateDependencies = (\n code: string,\n filename: string,\n evaluate = false,\n targetTemplateSpans?: ExpressionSpan[]\n): TemplateExtractionResult => {\n const program = parseOxc(code, filename);\n const analysis = analyzeProgram(program, {\n collectTemplateLiterals: true,\n templateSpanLookup: createSpanLookup(targetTemplateSpans),\n });\n const expressions = analysis.templateLiterals.flatMap(\n (template) => template.expressions\n );\n\n return extractExpressions(\n code,\n filename,\n evaluate,\n program,\n analysis,\n expressions\n );\n};\n"],"file":"expressionExtraction.js"}
1
+ {"mappings":"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","names":[],"sources":["../../../src/utils/collectOxcTemplateDependencies/expressionExtraction.ts"],"version":3,"sourcesContent":["/* eslint-disable no-restricted-syntax,no-continue */\n\nimport type { ExpressionValue } from '@wyw-in-js/shared';\nimport { ValueType } from '@wyw-in-js/shared';\nimport type { Expression, Program } from 'oxc-parser';\n\nimport { applyOxcReplacements } from '../oxc/replacements';\nimport { createOxcLocationLookup } from '../oxc/sourceLocations';\nimport {\n analyzeProgram,\n containsTaggedTemplateExpression,\n createSpanLookup,\n findReferences,\n getSourceLocation,\n isBindingDeclaredWithin,\n parseOxc,\n resolveBindingAt,\n} from './scopeAnalysis';\nimport {\n applyExpressionReplacements,\n collectIdentifierReferenceReplacements,\n collectStaticNamespaceMemberReferences,\n getConstantReplacement,\n replaceIdentifierReferences,\n} from './expressionReplacements';\nimport {\n cloneStaticValue,\n evaluateStatic,\n isStaticSerializableValue,\n literalCode,\n} from './staticEvaluator';\nimport type {\n Binding,\n ExtractedExpression,\n ExpressionSpan,\n ExtractionContext,\n OxcStaticImportReference,\n ProgramAnalysis,\n Replacement,\n StaticBindings,\n StaticLocalExpression,\n TemplateExtractionResult,\n} from './types';\n\nconst allocateExpressionName = (ctx: ExtractionContext): string => {\n let base = '_exp';\n let idx = 1;\n while (ctx.usedNames.has(base)) {\n idx += 1;\n base = `_exp${idx}`;\n }\n\n ctx.usedNames.add(base);\n return base;\n};\n\nconst hoistedBindingKey = (binding: Binding): string =>\n `${binding.scope.start}:${binding.scope.end}:${binding.declaredAt}:${binding.name}`;\n\nconst allocateHoistedBindingName = (\n originalName: string,\n ctx: ExtractionContext\n): string => {\n const sanitized = originalName.replace(/[^A-Za-z0-9_$]/g, '_') || 'hoisted';\n const base = /^[A-Za-z_$]/.test(sanitized) ? `_${sanitized}` : '_hoisted';\n let candidate = base;\n let idx = 2;\n\n while (ctx.usedNames.has(candidate)) {\n candidate = `${base}${idx}`;\n idx += 1;\n }\n\n ctx.usedNames.add(candidate);\n return candidate;\n};\n\nconst getHoistedBindingName = (\n binding: Binding,\n ctx: ExtractionContext\n): string => {\n const key = hoistedBindingKey(binding);\n const existing = ctx.hoistedBindingNames.get(key);\n if (existing) {\n return existing;\n }\n\n const next = allocateHoistedBindingName(binding.name, ctx);\n ctx.hoistedBindingNames.set(key, next);\n return next;\n};\n\nconst parenthesizeStaticReplacement = (source: string): string => `(${source})`;\n\nconst replaceStaticLocalReferences = (\n expression: Expression,\n replacements: Map<string, string>,\n ctx: ExtractionContext,\n extraReplacements: Replacement[] = []\n): string => {\n if (expression.type === 'Identifier' && extraReplacements.length === 0) {\n return (\n replacements.get(expression.name) ??\n ctx.code.slice(expression.start, expression.end)\n );\n }\n\n const parenthesized = new Map<string, string>();\n replacements.forEach((value, key) => {\n parenthesized.set(key, parenthesizeStaticReplacement(value));\n });\n\n return applyExpressionReplacements(\n expression,\n [\n ...extraReplacements,\n ...collectIdentifierReferenceReplacements(expression, parenthesized),\n ],\n ctx.code\n );\n};\n\nconst collectStaticLocalExpression = (\n expression: Expression,\n ctx: ExtractionContext,\n stack: string[] = []\n): StaticLocalExpression | null => {\n const replacements = new Map<string, string>();\n const importedFrom = new Set<string>();\n const imports: OxcStaticImportReference[] = [];\n\n for (const { name, start } of findReferences(\n expression,\n ctx.referencesByNode\n )) {\n const binding = resolveBindingAt(ctx, name, start);\n if (!binding) {\n return null;\n }\n\n if (binding.importedFrom) {\n importedFrom.add(binding.importedFrom);\n if (binding.imported && binding.imported !== '*') {\n imports.push({\n imported: binding.imported,\n local: binding.name,\n source: binding.importedFrom,\n });\n continue;\n }\n\n return null;\n }\n\n const replacement = getConstantReplacement(binding, ctx);\n if (replacement) {\n replacements.set(name, replacement);\n continue;\n }\n\n if (\n binding.kind === 'param' ||\n binding.declarationKind !== 'const' ||\n !binding.declarator?.init ||\n binding.declarator.id.type !== 'Identifier'\n ) {\n return null;\n }\n\n // Processor-managed bindings (const x = css``) carry their value\n // (the generated className string) via inlineConstants at candidate\n // evaluation time. Walking the TaggedTemplateExpression here would\n // pull the processor's tag import (e.g. `css` from '@linaria/core')\n // into the candidate's static imports, where it fails to resolve.\n // Leave the identifier as a free reference; the candidate-side env\n // supplies the className.\n if (binding.declarator.init.type === 'TaggedTemplateExpression') {\n continue;\n }\n\n const key = hoistedBindingKey(binding);\n if (stack.includes(key)) {\n return null;\n }\n\n const nested = collectStaticLocalExpression(binding.declarator.init, ctx, [\n ...stack,\n key,\n ]);\n if (!nested) {\n return null;\n }\n\n replacements.set(name, nested.source);\n nested.importedFrom.forEach((source) => importedFrom.add(source));\n imports.push(...nested.imports);\n }\n\n return {\n importedFrom: [...importedFrom],\n imports,\n source:\n replacements.size > 0\n ? replaceStaticLocalReferences(expression, replacements, ctx)\n : ctx.code.slice(expression.start, expression.end),\n };\n};\n\nconst declarationInitCode = (\n init: Expression,\n ctx: ExtractionContext\n): string => {\n const renamedDependencies = new Map<string, string>();\n findReferences(init, ctx.referencesByNode).forEach(({ name, start }) => {\n const dependency = resolveBindingAt(ctx, name, start);\n if (\n !dependency ||\n dependency.importedFrom ||\n dependency.isRoot ||\n dependency.declarator?.id.type !== 'Identifier'\n ) {\n return;\n }\n\n renamedDependencies.set(name, getHoistedBindingName(dependency, ctx));\n });\n\n return renamedDependencies.size > 0\n ? replaceIdentifierReferences(init, renamedDependencies, ctx.code)\n : ctx.code.slice(init.start, init.end);\n};\n\nconst addHoistedCode = (\n key: string,\n code: string,\n ctx: ExtractionContext\n): void => {\n if (ctx.hoistedDeclarations.has(key)) {\n return;\n }\n\n ctx.hoistedDeclarations.set(key, code);\n const declarations =\n ctx.hoistedDeclarationsByInsertionPoint.get(ctx.currentInsertionPoint) ??\n [];\n declarations.push(code);\n ctx.hoistedDeclarationsByInsertionPoint.set(\n ctx.currentInsertionPoint,\n declarations\n );\n};\n\nconst declarationCode = (binding: Binding, ctx: ExtractionContext): string => {\n const { declarator } = binding;\n if (!declarator) {\n return '';\n }\n\n const { id } = declarator;\n if (id.type !== 'Identifier') {\n const idCode = ctx.code.slice(id.start, id.end);\n if (!declarator.init) {\n return `let ${idCode};`;\n }\n\n return `let ${idCode} = ${declarationInitCode(declarator.init, ctx)};`;\n }\n\n const hoistedName = getHoistedBindingName(binding, ctx);\n if (!declarator.init) {\n return `let ${hoistedName};`;\n }\n\n return `let ${hoistedName} = ${declarationInitCode(declarator.init, ctx)};`;\n};\n\nconst assertHoistable = (\n binding: Binding,\n ctx: ExtractionContext,\n stack: string[] = []\n): void => {\n if (!binding.declarator?.init || binding.importedFrom || binding.isRoot) {\n return;\n }\n\n if (stack.includes(binding.name)) {\n return;\n }\n\n const refs = findReferences(binding.declarator.init, ctx.referencesByNode);\n refs.forEach(({ name, start }) => {\n const nextBinding = resolveBindingAt(ctx, name, start);\n if (!nextBinding) {\n return;\n }\n\n if (nextBinding.kind === 'param') {\n throw new Error(\n `This identifier cannot be used in the template, because it is a function parameter.`\n );\n }\n\n assertHoistable(nextBinding, ctx, [...stack, binding.name]);\n });\n};\n\nconst addHoistedDeclaration = (\n binding: Binding,\n ctx: ExtractionContext,\n stack: string[] = []\n): void => {\n if (\n !binding.declaration ||\n !binding.declarator ||\n binding.importedFrom ||\n binding.isRoot ||\n stack.includes(binding.name)\n ) {\n return;\n }\n\n const hoistSource = binding.declarator.init ?? binding.declarator;\n findReferences(hoistSource, ctx.referencesByNode).forEach(\n ({ name, start }) => {\n const dependency = resolveBindingAt(ctx, name, start);\n if (dependency) {\n addHoistedDeclaration(dependency, ctx, [...stack, binding.name]);\n }\n }\n );\n\n if (!ctx.hoistedDeclarations.has(binding.name)) {\n addHoistedCode(binding.name, declarationCode(binding, ctx), ctx);\n }\n};\n\nconst literalExpressionValue = (\n expression: Expression,\n ctx: ExtractionContext\n): Omit<ExpressionValue, 'buildCodeFrameError'> | null => {\n if (expression.type !== 'Literal') {\n return null;\n }\n\n if (\n expression.value !== null &&\n typeof expression.value !== 'string' &&\n typeof expression.value !== 'number' &&\n typeof expression.value !== 'boolean'\n ) {\n return null;\n }\n\n let type:\n | 'BooleanLiteral'\n | 'NullLiteral'\n | 'NumericLiteral'\n | 'StringLiteral';\n if (expression.value === null) {\n type = 'NullLiteral';\n } else if (typeof expression.value === 'string') {\n type = 'StringLiteral';\n } else if (typeof expression.value === 'number') {\n type = 'NumericLiteral';\n } else {\n type = 'BooleanLiteral';\n }\n\n const loc = getSourceLocation(expression.start, expression.end, ctx);\n const ex =\n expression.value === null\n ? { loc, type }\n : {\n loc,\n type,\n value: expression.value,\n };\n\n return {\n ex,\n kind: ValueType.CONST,\n source: ctx.code.slice(expression.start, expression.end),\n value: expression.value,\n } as unknown as Omit<ExpressionValue, 'buildCodeFrameError'>;\n};\n\nconst extractExpression = (\n expression: Expression,\n ctx: ExtractionContext,\n evaluate: boolean\n): ExtractedExpression => {\n const source = ctx.code.slice(expression.start, expression.end);\n // Only inline function expressions are function-valued here. A bare\n // identifier that points to a local function may be a styled runtime\n // component, so it has to stay as a lazy `_exp()` reference.\n const isFunction =\n expression.type === 'FunctionExpression' ||\n expression.type === 'ArrowFunctionExpression';\n\n if (evaluate) {\n const evaluated = evaluateStatic(expression, ctx);\n const literal = literalCode(evaluated);\n if (literal) {\n findReferences(expression, ctx.referencesByNode).forEach(({ name }) =>\n ctx.dependencyNames.add(name)\n );\n return {\n expressionCode: literal,\n importedFrom: [],\n kind: isFunction ? ValueType.FUNCTION : ValueType.LAZY,\n staticImports: [],\n staticValue: isStaticSerializableValue(evaluated)\n ? cloneStaticValue(evaluated)\n : undefined,\n };\n }\n }\n\n const identifierReplacements = new Map<string, string>();\n const importedFrom: string[] = [];\n const namespaceStatic = collectStaticNamespaceMemberReferences(\n expression,\n ctx\n );\n const staticIdentifierReplacements = new Map<string, string>();\n const staticImports: OxcStaticImportReference[] = [\n ...namespaceStatic.imports,\n ];\n let hasNonStaticLocalReference = false;\n let hasInlinableLocalReference = false;\n\n findReferences(expression, ctx.referencesByNode).forEach(\n ({ name, start }) => {\n const binding = resolveBindingAt(ctx, name, start);\n if (!binding) {\n return;\n }\n\n if (isFunction && isBindingDeclaredWithin(binding, expression)) {\n return;\n }\n\n ctx.dependencyNames.add(name);\n\n if (binding.importedFrom) {\n importedFrom.push(binding.importedFrom);\n if (binding.imported && binding.imported !== '*') {\n staticImports.push({\n imported: binding.imported,\n local: binding.name,\n source: binding.importedFrom,\n });\n } else if (\n binding.imported === '*' &&\n namespaceStatic.coveredReferenceStarts.has(start)\n ) {\n // The static candidate source gets a synthetic named import alias,\n // while the eval fallback keeps the original namespace expression.\n } else {\n hasNonStaticLocalReference = true;\n }\n return;\n }\n\n const replacement = getConstantReplacement(binding, ctx);\n if (evaluate && replacement) {\n identifierReplacements.set(name, replacement);\n return;\n }\n\n const init = binding.declarator?.init;\n // Processor-managed bindings (`const x = css```, or object literals\n // containing processor tags) carry values that only become known after\n // processors run. Leave the identifier free in the candidate source so\n // the resolver can supply it via inlineConstants at evaluation time.\n const isProcessorManagedLocal =\n !!evaluate && !!init && containsTaggedTemplateExpression(init);\n const staticLocalExpression =\n evaluate && init && !isProcessorManagedLocal\n ? collectStaticLocalExpression(init, ctx, [\n hoistedBindingKey(binding),\n ])\n : null;\n if (staticLocalExpression) {\n staticIdentifierReplacements.set(name, staticLocalExpression.source);\n importedFrom.push(...staticLocalExpression.importedFrom);\n staticImports.push(...staticLocalExpression.imports);\n } else if (isProcessorManagedLocal) {\n hasInlinableLocalReference = true;\n } else {\n hasNonStaticLocalReference = true;\n }\n\n if (!isProcessorManagedLocal) {\n assertHoistable(binding, ctx);\n addHoistedDeclaration(binding, ctx);\n if (!binding.isRoot && binding.declarator?.id.type === 'Identifier') {\n identifierReplacements.set(name, getHoistedBindingName(binding, ctx));\n }\n }\n }\n );\n\n // Merge literal-const inlines (e.g. `const A = 32` -> \"32\") with\n // local-to-imported substitutions (e.g. `const X = imp.y` -> \"imp.y\").\n // Both must reach the candidate source so the resolver's evaluator\n // can fold every Identifier in the expression; env only carries\n // imported bindings, never same-file locals.\n const mergedReplacements = new Map(staticIdentifierReplacements);\n identifierReplacements.forEach((value, key) => {\n if (!mergedReplacements.has(key)) {\n mergedReplacements.set(key, value);\n }\n });\n\n let staticExpressionCode: string | undefined;\n if (mergedReplacements.size > 0) {\n staticExpressionCode = replaceStaticLocalReferences(\n expression,\n mergedReplacements,\n ctx,\n namespaceStatic.replacements\n );\n } else if (namespaceStatic.replacements.length > 0) {\n staticExpressionCode = applyExpressionReplacements(\n expression,\n namespaceStatic.replacements,\n ctx.code\n );\n }\n\n return {\n expressionCode:\n identifierReplacements.size > 0\n ? replaceIdentifierReferences(\n expression,\n identifierReplacements,\n ctx.code\n )\n : source,\n importedFrom,\n kind: isFunction ? ValueType.FUNCTION : ValueType.LAZY,\n staticExpressionCode,\n hasInlinableLocalReference:\n !hasNonStaticLocalReference && hasInlinableLocalReference,\n staticImports: hasNonStaticLocalReference ? [] : staticImports,\n };\n};\n\nconst getInsertionPoints = (\n program: Program,\n expressions: Expression[]\n): number[] => {\n if (expressions.length === 0) {\n return [];\n }\n\n if (program.body.length === 0) {\n return expressions.map(() => 0);\n }\n\n const insertionPoints: number[] = [];\n let ownerIndex = 0;\n\n expressions.forEach((expression) => {\n while (\n ownerIndex < program.body.length - 1 &&\n program.body[ownerIndex]!.end < expression.start\n ) {\n ownerIndex += 1;\n }\n\n let owner: Program['body'][number] | undefined = program.body[ownerIndex];\n if (\n !owner ||\n owner.start > expression.start ||\n owner.end < expression.end\n ) {\n owner = program.body.find(\n (statement) =>\n statement.start <= expression.start && statement.end >= expression.end\n );\n }\n\n insertionPoints.push(owner?.start ?? 0);\n });\n\n return insertionPoints;\n};\n\nconst extractExpressions = (\n code: string,\n filename: string,\n evaluate: boolean,\n program: Program,\n analysis: Pick<\n ProgramAnalysis,\n 'bindingsByName' | 'rootMutationsByBinding' | 'usedNames'\n >,\n expressions: Expression[],\n staticBindings?: StaticBindings\n): TemplateExtractionResult => {\n if (expressions.length === 0) {\n return {\n code,\n dependencyNames: [],\n expressionValues: [],\n staticValueCandidates: [],\n staticValues: [],\n };\n }\n\n const insertionPoints = getInsertionPoints(program, expressions);\n const ctx: ExtractionContext = {\n bindingResolutionCache: new Map(),\n bindingsByName: analysis.bindingsByName,\n code,\n currentInsertionPoint: insertionPoints[0] ?? 0,\n currentExpressionStart: expressions[0].start,\n dependencyNames: new Set(),\n expressionValues: [],\n filename,\n hoistedBindingNames: new Map(),\n hoistedDeclarations: new Map(),\n hoistedDeclarationsByInsertionPoint: new Map(),\n loc: createOxcLocationLookup(code),\n referencesByNode: new WeakMap(),\n replacements: [],\n rootMutationsByBinding: analysis.rootMutationsByBinding,\n staticBindings,\n staticImportAliases: new Map(),\n staticValueCandidates: [],\n staticValues: [],\n usedNames: new Set(analysis.usedNames),\n };\n\n expressions.forEach((expression, index) => {\n ctx.currentInsertionPoint = insertionPoints[index] ?? 0;\n ctx.currentExpressionStart = expression.start;\n\n const literal = literalExpressionValue(expression, ctx);\n if (literal) {\n ctx.expressionValues.push(literal);\n return;\n }\n\n const {\n expressionCode,\n hasInlinableLocalReference,\n importedFrom,\n kind,\n staticExpressionCode,\n staticImports,\n staticValue,\n } = extractExpression(expression, ctx, evaluate);\n const expName = allocateExpressionName(ctx);\n\n addHoistedCode(\n expName,\n `const ${expName} = () => (${expressionCode});`,\n ctx\n );\n if (staticValue !== undefined && kind !== ValueType.FUNCTION) {\n ctx.staticValues.push({\n name: expName,\n value: staticValue,\n });\n } else if (\n (staticImports.length > 0 ||\n hasInlinableLocalReference ||\n staticExpressionCode !== undefined) &&\n kind !== ValueType.FUNCTION\n ) {\n const uniqueImports = new Map<string, OxcStaticImportReference>();\n staticImports.forEach((item) => {\n uniqueImports.set(\n `${item.local}\\0${item.importLocal ?? ''}\\0${item.source}\\0${\n item.imported\n }`,\n item\n );\n });\n ctx.staticValueCandidates.push({\n imports: [...uniqueImports.values()],\n name: expName,\n source: staticExpressionCode ?? expressionCode,\n });\n }\n ctx.replacements.push({\n start: expression.start,\n end: expression.end,\n value: `${expName}()`,\n });\n ctx.expressionValues.push({\n ex: {\n loc: getSourceLocation(expression.start, expression.end, ctx),\n name: expName,\n type: 'Identifier',\n },\n importedFrom,\n kind,\n source: ctx.code.slice(expression.start, expression.end),\n } as unknown as Omit<ExpressionValue, 'buildCodeFrameError'>);\n });\n\n ctx.hoistedDeclarationsByInsertionPoint.forEach((declarations, point) => {\n ctx.replacements.push({\n start: point,\n end: point,\n value: `${declarations.join('\\n')}\\n`,\n });\n });\n\n return {\n code: applyOxcReplacements(code, ctx.replacements),\n dependencyNames: [...ctx.dependencyNames],\n expressionValues: ctx.expressionValues,\n staticValueCandidates: ctx.staticValueCandidates,\n staticValues: ctx.staticValues,\n };\n};\n\nexport const isOxcStaticSerializableValue = (value: unknown): boolean =>\n isStaticSerializableValue(value);\n\nexport const evaluateOxcStaticExpressionAt = (\n code: string,\n filename: string,\n expressionSpan: ExpressionSpan,\n env: Map<string, unknown> = new Map(),\n staticBindings?: StaticBindings\n): unknown | undefined => {\n const program = parseOxc(code, filename);\n const analysis = analyzeProgram(program, {\n collectTargetExpressions: true,\n expressionSpanLookup: createSpanLookup([expressionSpan]),\n });\n const [expression] = analysis.targetExpressions;\n if (!expression) {\n return undefined;\n }\n\n const ctx: ExtractionContext = {\n bindingResolutionCache: new Map(),\n bindingsByName: analysis.bindingsByName,\n code,\n currentInsertionPoint: 0,\n currentExpressionStart: expression.start,\n dependencyNames: new Set(),\n expressionValues: [],\n filename,\n hoistedBindingNames: new Map(),\n hoistedDeclarations: new Map(),\n hoistedDeclarationsByInsertionPoint: new Map(),\n loc: createOxcLocationLookup(code),\n referencesByNode: new WeakMap(),\n replacements: [],\n rootMutationsByBinding: analysis.rootMutationsByBinding,\n staticBindings,\n staticImportAliases: new Map(),\n staticValueCandidates: [],\n staticValues: [],\n usedNames: new Set(analysis.usedNames),\n };\n\n return evaluateStatic(expression, ctx, new Map(env));\n};\n\nexport const evaluateOxcStaticExpression = (\n source: string,\n filename: string,\n env: Map<string, unknown> = new Map(),\n staticBindings?: StaticBindings\n): unknown | undefined => {\n const code = `const __wyw_static_value = ${source};`;\n const program = parseOxc(code, filename);\n const declaration = program.body[0];\n if (declaration?.type !== 'VariableDeclaration') {\n return undefined;\n }\n\n const [declarator] = declaration.declarations;\n if (!declarator?.init) {\n return undefined;\n }\n\n return evaluateOxcStaticExpressionAt(\n code,\n filename,\n {\n end: declarator.init.end,\n start: declarator.init.start,\n },\n env,\n staticBindings\n );\n};\n\nexport const collectOxcExpressionDependencies = (\n code: string,\n filename: string,\n evaluate = false,\n targetExpressionSpans?: ExpressionSpan[],\n staticBindings?: StaticBindings\n): TemplateExtractionResult => {\n const program = parseOxc(code, filename);\n const analysis = analyzeProgram(program, {\n collectTargetExpressions: true,\n expressionSpanLookup: createSpanLookup(targetExpressionSpans),\n });\n\n return extractExpressions(\n code,\n filename,\n evaluate,\n program,\n analysis,\n analysis.targetExpressions,\n staticBindings\n );\n};\n\nexport const collectOxcTemplateDependencies = (\n code: string,\n filename: string,\n evaluate = false,\n targetTemplateSpans?: ExpressionSpan[]\n): TemplateExtractionResult => {\n const program = parseOxc(code, filename);\n const analysis = analyzeProgram(program, {\n collectTemplateLiterals: true,\n templateSpanLookup: createSpanLookup(targetTemplateSpans),\n });\n const expressions = analysis.templateLiterals.flatMap(\n (template) => template.expressions\n );\n\n return extractExpressions(\n code,\n filename,\n evaluate,\n program,\n analysis,\n expressions\n );\n};\n"],"file":"expressionExtraction.js"}
@@ -1,28 +1,58 @@
1
1
  export const isOxcNode = (value) => !!value && typeof value === "object" && "type" in value && typeof value.type === "string";
2
+ // Cache visitor-key lists per node.type. oxc-parser AST nodes have a stable
3
+ // shape per `type` — optional children are present as null/undefined, not
4
+ // omitted — so Object.keys() returns the same key set for every instance of
5
+ // the same kind. First instance pays the discovery cost; the rest do an
6
+ // indexed lookup. getOxcNodeChildren is invoked tens of millions of times
7
+ // on a cold build of a large monorepo, so this matters a lot.
8
+ //
9
+ // An instance-level WeakMap cache of the resulting Node[] was tried and
10
+ // regressed wall time ~20% (WeakMap.get/set per call beat the recompute
11
+ // savings for small children arrays + pinned arrays into older generations
12
+ // and increased GC pressure). Per-type key cache only.
13
+ const META_KEYS = new Set([
14
+ "comments",
15
+ "end",
16
+ "errors",
17
+ "parent",
18
+ "range",
19
+ "span",
20
+ "start",
21
+ "type"
22
+ ]);
23
+ const VISITOR_KEYS_BY_TYPE = new Map();
24
+ const visitorKeysFor = (node) => {
25
+ let keys = VISITOR_KEYS_BY_TYPE.get(node.type);
26
+ if (keys === undefined) {
27
+ keys = Object.keys(node).filter((key) => !META_KEYS.has(key));
28
+ VISITOR_KEYS_BY_TYPE.set(node.type, keys);
29
+ }
30
+ return keys;
31
+ };
2
32
  export const getOxcNodeChildren = (node) => {
3
33
  const result = [];
4
34
  const record = node;
5
- Object.keys(record).forEach((key) => {
6
- if (key === "comments" || key === "end" || key === "errors" || key === "parent" || key === "range" || key === "span" || key === "start" || key === "type") {
7
- return;
8
- }
9
- const value = record[key];
35
+ const keys = visitorKeysFor(record);
36
+ for (let i = 0; i < keys.length; i += 1) {
37
+ const value = record[keys[i]];
10
38
  if (isOxcNode(value)) {
11
39
  result.push(value);
12
- return;
13
- }
14
- if (Array.isArray(value)) {
15
- value.forEach((item) => {
40
+ } else if (Array.isArray(value)) {
41
+ for (let j = 0; j < value.length; j += 1) {
42
+ const item = value[j];
16
43
  if (isOxcNode(item)) {
17
44
  result.push(item);
18
45
  }
19
- });
46
+ }
20
47
  }
21
- });
48
+ }
22
49
  return result;
23
50
  };
24
51
  export const walkOxc = (node, enter, parent = null) => {
25
52
  enter(node, parent);
26
- getOxcNodeChildren(node).forEach((child) => walkOxc(child, enter, node));
53
+ const children = getOxcNodeChildren(node);
54
+ for (let i = 0; i < children.length; i += 1) {
55
+ walkOxc(children[i], enter, node);
56
+ }
27
57
  };
28
58
  //# sourceMappingURL=ast.js.map
@@ -1 +1 @@
1
- {"mappings":"AAIA,OAAO,MAAM,aAAa,UACxB,CAAC,CAAC,SACF,OAAO,UAAU,YACjB,UAAU,SACV,OAAQ,MAA6B,SAAS;AAEhD,OAAO,MAAM,sBAAsB,SAAuB;CACxD,MAAM,SAAiB,EAAE;CACzB,MAAM,SAAS;AAEf,QAAO,KAAK,OAAO,CAAC,SAAS,QAAQ;AACnC,MACE,QAAQ,cACR,QAAQ,SACR,QAAQ,YACR,QAAQ,YACR,QAAQ,WACR,QAAQ,UACR,QAAQ,WACR,QAAQ,QACR;AACA;;EAGF,MAAM,QAAQ,OAAO;AACrB,MAAI,UAAU,MAAM,EAAE;AACpB,UAAO,KAAK,MAAM;AAClB;;AAGF,MAAI,MAAM,QAAQ,MAAM,EAAE;AACxB,SAAM,SAAS,SAAS;AACtB,QAAI,UAAU,KAAK,EAAE;AACnB,YAAO,KAAK,KAAK;;KAEnB;;GAEJ;AAEF,QAAO;;AAGT,OAAO,MAAM,WACX,MACA,OACA,SAAsB,SACb;AACT,OAAM,MAAM,OAAO;AACnB,oBAAmB,KAAK,CAAC,SAAS,UAAU,QAAQ,OAAO,OAAO,KAAK,CAAC","names":[],"sources":["../../../src/utils/oxc/ast.ts"],"version":3,"sourcesContent":["import type { Node } from 'oxc-parser';\n\ntype AnyOxcNode = Node & Record<string, unknown>;\n\nexport const isOxcNode = (value: unknown): value is Node =>\n !!value &&\n typeof value === 'object' &&\n 'type' in value &&\n typeof (value as { type?: unknown }).type === 'string';\n\nexport const getOxcNodeChildren = (node: Node): Node[] => {\n const result: Node[] = [];\n const record = node as AnyOxcNode;\n\n Object.keys(record).forEach((key) => {\n if (\n key === 'comments' ||\n key === 'end' ||\n key === 'errors' ||\n key === 'parent' ||\n key === 'range' ||\n key === 'span' ||\n key === 'start' ||\n key === 'type'\n ) {\n return;\n }\n\n const value = record[key];\n if (isOxcNode(value)) {\n result.push(value);\n return;\n }\n\n if (Array.isArray(value)) {\n value.forEach((item) => {\n if (isOxcNode(item)) {\n result.push(item);\n }\n });\n }\n });\n\n return result;\n};\n\nexport const walkOxc = (\n node: Node,\n enter: (node: Node, parent: Node | null) => void,\n parent: Node | null = null\n): void => {\n enter(node, parent);\n getOxcNodeChildren(node).forEach((child) => walkOxc(child, enter, node));\n};\n"],"file":"ast.js"}
1
+ {"mappings":"AAIA,OAAO,MAAM,aAAa,UACxB,CAAC,CAAC,SACF,OAAO,UAAU,YACjB,UAAU,SACV,OAAQ,MAA6B,SAAS;;;;;;;;;;;;AAahD,MAAM,YAAY,IAAI,IAAI;CACxB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AACF,MAAM,uBAAuB,IAAI,KAAgC;AACjE,MAAM,kBAAkB,SAAwC;CAC9D,IAAI,OAAO,qBAAqB,IAAI,KAAK,KAAK;AAC9C,KAAI,SAAS,WAAW;AACtB,SAAO,OAAO,KAAK,KAAK,CAAC,QAAQ,QAAQ,CAAC,UAAU,IAAI,IAAI,CAAC;AAC7D,uBAAqB,IAAI,KAAK,MAAM,KAAK;;AAE3C,QAAO;;AAGT,OAAO,MAAM,sBAAsB,SAAuB;CACxD,MAAM,SAAiB,EAAE;CACzB,MAAM,SAAS;CACf,MAAM,OAAO,eAAe,OAAO;AACnC,MAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK,GAAG;EACvC,MAAM,QAAQ,OAAO,KAAK;AAC1B,MAAI,UAAU,MAAM,EAAE;AACpB,UAAO,KAAK,MAAM;aACT,MAAM,QAAQ,MAAM,EAAE;AAC/B,QAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;IACxC,MAAM,OAAO,MAAM;AACnB,QAAI,UAAU,KAAK,EAAE;AACnB,YAAO,KAAK,KAAK;;;;;AAKzB,QAAO;;AAGT,OAAO,MAAM,WACX,MACA,OACA,SAAsB,SACb;AACT,OAAM,MAAM,OAAO;CACnB,MAAM,WAAW,mBAAmB,KAAK;AACzC,MAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK,GAAG;AAC3C,UAAQ,SAAS,IAAI,OAAO,KAAK","names":[],"sources":["../../../src/utils/oxc/ast.ts"],"version":3,"sourcesContent":["import type { Node } from 'oxc-parser';\n\ntype AnyOxcNode = Node & Record<string, unknown>;\n\nexport const isOxcNode = (value: unknown): value is Node =>\n !!value &&\n typeof value === 'object' &&\n 'type' in value &&\n typeof (value as { type?: unknown }).type === 'string';\n\n// Cache visitor-key lists per node.type. oxc-parser AST nodes have a stable\n// shape per `type` optional children are present as null/undefined, not\n// omitted — so Object.keys() returns the same key set for every instance of\n// the same kind. First instance pays the discovery cost; the rest do an\n// indexed lookup. getOxcNodeChildren is invoked tens of millions of times\n// on a cold build of a large monorepo, so this matters a lot.\n//\n// An instance-level WeakMap cache of the resulting Node[] was tried and\n// regressed wall time ~20% (WeakMap.get/set per call beat the recompute\n// savings for small children arrays + pinned arrays into older generations\n// and increased GC pressure). Per-type key cache only.\nconst META_KEYS = new Set([\n 'comments',\n 'end',\n 'errors',\n 'parent',\n 'range',\n 'span',\n 'start',\n 'type',\n]);\nconst VISITOR_KEYS_BY_TYPE = new Map<string, readonly string[]>();\nconst visitorKeysFor = (node: AnyOxcNode): readonly string[] => {\n let keys = VISITOR_KEYS_BY_TYPE.get(node.type);\n if (keys === undefined) {\n keys = Object.keys(node).filter((key) => !META_KEYS.has(key));\n VISITOR_KEYS_BY_TYPE.set(node.type, keys);\n }\n return keys;\n};\n\nexport const getOxcNodeChildren = (node: Node): Node[] => {\n const result: Node[] = [];\n const record = node as AnyOxcNode;\n const keys = visitorKeysFor(record);\n for (let i = 0; i < keys.length; i += 1) {\n const value = record[keys[i]];\n if (isOxcNode(value)) {\n result.push(value);\n } else if (Array.isArray(value)) {\n for (let j = 0; j < value.length; j += 1) {\n const item = value[j];\n if (isOxcNode(item)) {\n result.push(item);\n }\n }\n }\n }\n return result;\n};\n\nexport const walkOxc = (\n node: Node,\n enter: (node: Node, parent: Node | null) => void,\n parent: Node | null = null\n): void => {\n enter(node, parent);\n const children = getOxcNodeChildren(node);\n for (let i = 0; i < children.length; i += 1) {\n walkOxc(children[i], enter, node);\n }\n};\n"],"file":"ast.js"}
@@ -1,5 +1,6 @@
1
1
  import { collectOxcExportsAndImports } from "./collectOxcExportsAndImports.js";
2
2
  import { EventEmitter } from "./EventEmitter.js";
3
+ import { getOxcNodeChildren } from "./oxc/ast.js";
3
4
  import { parseOxcProgramCached } from "./parseOxc.js";
4
5
  const ssrCheckFields = new Set([
5
6
  "document",
@@ -97,28 +98,11 @@ const getStaticBinding = (scope, name) => {
97
98
  };
98
99
  const isFileLikeRequireSpecifier = (value) => value.startsWith(".") || value.startsWith("/") || value.startsWith("file:");
99
100
  const isNode = (value) => !!value && typeof value === "object" && "type" in value && typeof value.type === "string";
100
- const getChildren = (node) => {
101
- const result = [];
102
- const record = node;
103
- Object.keys(record).forEach((key) => {
104
- if (key === "type" || key === "start" || key === "end" || key === "range") {
105
- return;
106
- }
107
- const value = record[key];
108
- if (isNode(value)) {
109
- result.push(value);
110
- return;
111
- }
112
- if (Array.isArray(value)) {
113
- value.forEach((item) => {
114
- if (isNode(item)) {
115
- result.push(item);
116
- }
117
- });
118
- }
119
- });
120
- return result;
121
- };
101
+ // Reuses the per-node.type visitor-key cache in utils/oxc/ast.ts. This file's
102
+ // getChildren shape historically diverged from the canonical one (a smaller
103
+ // metadata-key skip set), but the produced children list is identical in
104
+ // practice because oxc-parser nodes don't carry the extra metadata fields.
105
+ const getChildren = getOxcNodeChildren;
122
106
  const parseOxc = (code, filename) => {
123
107
  return parseOxcProgramCached(filename, code, "unambiguous");
124
108
  };
@@ -314,57 +298,92 @@ const predeclareScopeNames = (node, scope) => {
314
298
  });
315
299
  }
316
300
  const visitScopeDescendants = (child) => {
317
- if (child.type === "VariableDeclarator") {
318
- collectBindingNames(child.id).forEach((name) => {
319
- scope.names.add(name);
320
- });
321
- } else if (child.type === "FunctionDeclaration" && child.id) {
322
- scope.names.add(child.id.name);
323
- } else if (child.type === "ClassDeclaration" && child.id) {
324
- scope.names.add(child.id.name);
325
- } else if (child.type === "ImportDefaultSpecifier" || child.type === "ImportNamespaceSpecifier" || child.type === "ImportSpecifier") {
326
- scope.names.add(child.local.name);
301
+ switch (child.type) {
302
+ case "VariableDeclarator": {
303
+ const names = collectBindingNames(child.id);
304
+ for (let i = 0; i < names.length; i += 1) {
305
+ scope.names.add(names[i]);
306
+ }
307
+ break;
308
+ }
309
+ case "FunctionDeclaration":
310
+ case "ClassDeclaration":
311
+ if (child.id) {
312
+ scope.names.add(child.id.name);
313
+ }
314
+ break;
315
+ case "ImportDefaultSpecifier":
316
+ case "ImportNamespaceSpecifier":
317
+ case "ImportSpecifier":
318
+ scope.names.add(child.local.name);
319
+ break;
320
+ default: break;
327
321
  }
328
322
  if (createsScope(child)) {
329
323
  return;
330
324
  }
331
- getChildren(child).forEach(visitScopeDescendants);
325
+ const children = getChildren(child);
326
+ for (let i = 0; i < children.length; i += 1) {
327
+ visitScopeDescendants(children[i]);
328
+ }
332
329
  };
333
- getChildren(node).forEach(visitScopeDescendants);
330
+ const rootChildren = getChildren(node);
331
+ for (let i = 0; i < rootChildren.length; i += 1) {
332
+ visitScopeDescendants(rootChildren[i]);
333
+ }
334
334
  };
335
335
  const declareBindings = (node, scope) => {
336
- if (node.type === "VariableDeclarator") {
337
- const names = collectBindingNames(node.id);
338
- names.forEach((name) => {
339
- scope.names.add(name);
340
- scope.bindings.set(name, null);
341
- });
342
- if (node.id.type === "Identifier" && node.init) {
343
- scope.bindings.set(node.id.name, node.init);
344
- }
345
- return;
346
- }
347
- if (node.type === "FunctionDeclaration" && node.id) {
348
- scope.names.add(node.id.name);
349
- scope.bindings.set(node.id.name, null);
350
- }
351
- if (node.type === "ClassDeclaration" && node.id) {
352
- scope.names.add(node.id.name);
353
- scope.bindings.set(node.id.name, null);
354
- return;
355
- }
356
- if (node.type === "ImportDefaultSpecifier" || node.type === "ImportNamespaceSpecifier" || node.type === "ImportSpecifier") {
357
- scope.names.add(node.local.name);
358
- scope.bindings.set(node.local.name, null);
359
- return;
360
- }
361
- if (node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression") {
362
- node.params.forEach((param) => {
363
- collectBindingNames(param).forEach((name) => {
336
+ // Called for every visited AST node, so the dispatch is hot. A switch lets
337
+ // V8 generate a jump table on node.type; the previous chained `if`s walked
338
+ // each branch's string-compare for every non-matching node.
339
+ switch (node.type) {
340
+ case "VariableDeclarator": {
341
+ const names = collectBindingNames(node.id);
342
+ for (let i = 0; i < names.length; i += 1) {
343
+ const name = names[i];
364
344
  scope.names.add(name);
365
345
  scope.bindings.set(name, null);
366
- });
367
- });
346
+ }
347
+ if (node.id.type === "Identifier" && node.init) {
348
+ scope.bindings.set(node.id.name, node.init);
349
+ }
350
+ return;
351
+ }
352
+ case "ClassDeclaration": {
353
+ if (node.id) {
354
+ scope.names.add(node.id.name);
355
+ scope.bindings.set(node.id.name, null);
356
+ }
357
+ return;
358
+ }
359
+ case "ImportDefaultSpecifier":
360
+ case "ImportNamespaceSpecifier":
361
+ case "ImportSpecifier": {
362
+ scope.names.add(node.local.name);
363
+ scope.bindings.set(node.local.name, null);
364
+ return;
365
+ }
366
+ case "FunctionDeclaration": {
367
+ if (node.id) {
368
+ scope.names.add(node.id.name);
369
+ scope.bindings.set(node.id.name, null);
370
+ }
371
+ }
372
+ // eslint-disable-next-line no-fallthrough
373
+ case "FunctionExpression":
374
+ case "ArrowFunctionExpression": {
375
+ const { params } = node;
376
+ for (let i = 0; i < params.length; i += 1) {
377
+ const names = collectBindingNames(params[i]);
378
+ for (let j = 0; j < names.length; j += 1) {
379
+ const name = names[j];
380
+ scope.names.add(name);
381
+ scope.bindings.set(name, null);
382
+ }
383
+ }
384
+ break;
385
+ }
386
+ default: break;
368
387
  }
369
388
  };
370
389
  const visit = (node, scope, enter, parent = null, ancestors = []) => {
@@ -375,7 +394,17 @@ const visit = (node, scope, enter, parent = null, ancestors = []) => {
375
394
  }
376
395
  declareBindings(node, currentScope);
377
396
  enter(node, currentScope, parent, ancestors);
378
- getChildren(node).forEach((child) => visit(child, currentScope, enter, node, [...ancestors, node]));
397
+ // Push onto a shared ancestors stack instead of allocating `[...ancestors,
398
+ // node]` per child step (O(n × depth) extra allocation on deep ASTs).
399
+ // Every consumer of `ancestors` in this file reads it synchronously inside
400
+ // the enter callback; future callers that need to retain the reference
401
+ // must .slice() it themselves.
402
+ ancestors.push(node);
403
+ const children = getChildren(node);
404
+ for (let i = 0; i < children.length; i += 1) {
405
+ visit(children[i], currentScope, enter, node, ancestors);
406
+ }
407
+ ancestors.pop();
379
408
  };
380
409
  export const replaceImportMetaEnvWithOxc = (code, filename) => {
381
410
  if (!importMetaEnvRe.test(code)) {