@tanstack/start-plugin-core 1.169.17 → 1.169.19

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 (29) hide show
  1. package/dist/esm/import-protection/analysis.d.ts +5 -5
  2. package/dist/esm/import-protection/analysis.js +13 -9
  3. package/dist/esm/import-protection/analysis.js.map +1 -1
  4. package/dist/esm/import-protection/rewrite.js +5 -3
  5. package/dist/esm/import-protection/rewrite.js.map +1 -1
  6. package/dist/esm/import-protection/sourceLocation.d.ts +3 -2
  7. package/dist/esm/import-protection/sourceLocation.js +1 -0
  8. package/dist/esm/import-protection/sourceLocation.js.map +1 -1
  9. package/dist/esm/rsbuild/import-protection.js +9 -6
  10. package/dist/esm/rsbuild/import-protection.js.map +1 -1
  11. package/dist/esm/rsbuild/plugin.js +1 -0
  12. package/dist/esm/rsbuild/plugin.js.map +1 -1
  13. package/dist/esm/start-compiler/compiler.d.ts +4 -2
  14. package/dist/esm/start-compiler/compiler.js +8 -4
  15. package/dist/esm/start-compiler/compiler.js.map +1 -1
  16. package/dist/esm/vite/import-protection-plugin/plugin.js +4 -3
  17. package/dist/esm/vite/import-protection-plugin/plugin.js.map +1 -1
  18. package/package.json +8 -8
  19. package/src/import-protection/analysis.ts +22 -10
  20. package/src/import-protection/rewrite.ts +4 -5
  21. package/src/import-protection/sourceLocation.ts +4 -2
  22. package/src/rsbuild/import-protection.ts +7 -5
  23. package/src/rsbuild/plugin.ts +3 -0
  24. package/src/start-compiler/compiler.ts +13 -3
  25. package/src/vite/import-protection-plugin/plugin.ts +4 -3
  26. package/dist/esm/import-protection/ast.d.ts +0 -3
  27. package/dist/esm/import-protection/ast.js +0 -9
  28. package/dist/esm/import-protection/ast.js.map +0 -1
  29. package/src/import-protection/ast.ts +0 -7
@@ -1,5 +1,5 @@
1
1
  import { LineIndex, TransformResult } from './sourceLocation.js';
2
- import { ParsedAst } from './ast.js';
2
+ import { ParseAstResult } from '@tanstack/router-utils';
3
3
  export type UsagePos = {
4
4
  line: number;
5
5
  column0: number;
@@ -11,7 +11,7 @@ type ImportBindingInfo = {
11
11
  };
12
12
  type UsageCacheKey = `${BoundaryEnv | 'post'}::${string}`;
13
13
  export type ImportAnalysis = {
14
- ast: ParsedAst;
14
+ ast: ParseAstResult;
15
15
  lineIndex: LineIndex;
16
16
  importSourcesInOrder: Array<string>;
17
17
  importSpecifierLocationIndex: Map<string, number>;
@@ -23,12 +23,12 @@ export type ImportAnalysis = {
23
23
  export declare function isValidExportName(name: string): boolean;
24
24
  export declare function getOrCreateImportAnalysis(result: TransformResult): ImportAnalysis;
25
25
  export declare function getImportSourcesFromResult(result: TransformResult): Array<string>;
26
- export declare function getImportSources(code: string): Array<string>;
26
+ export declare function getImportSources(code: string, filename?: string): Array<string>;
27
27
  export declare function getImportSpecifierLocationFromResult(result: TransformResult, source: string): number;
28
28
  export declare function getMockExportNamesBySourceFromResult(result: TransformResult): Map<string, Array<string>>;
29
- export declare function getMockExportNamesBySource(code: string): Map<string, Array<string>>;
29
+ export declare function getMockExportNamesBySource(code: string, filename?: string): Map<string, Array<string>>;
30
30
  export declare function getNamedExportsFromResult(result: TransformResult): Array<string>;
31
- export declare function getNamedExports(code: string): Array<string>;
31
+ export declare function getNamedExports(code: string, filename?: string): Array<string>;
32
32
  export declare function findPostCompileUsagePosFromResult(result: TransformResult, source: string): UsagePos | undefined;
33
33
  export declare function findPostCompileUsagePos(code: string, source: string): UsagePos | undefined;
34
34
  export declare function findOriginalUnsafeUsagePosFromResult(result: TransformResult, source: string, envType: BoundaryEnv): UsagePos | undefined;
@@ -1,11 +1,12 @@
1
1
  import { getOrCreate } from "./utils.js";
2
- import { parseImportProtectionAst } from "./ast.js";
3
2
  import { buildLineIndex } from "./sourceLocation.js";
4
3
  import * as t from "@babel/types";
4
+ import { parseAst } from "@tanstack/router-utils";
5
5
  //#region src/import-protection/analysis.ts
6
- function makeTransientResult(code) {
6
+ function makeTransientResult(code, filename) {
7
7
  return {
8
8
  code,
9
+ filename,
9
10
  map: void 0,
10
11
  originalCode: void 0
11
12
  };
@@ -49,7 +50,10 @@ function isValidExportName(name) {
49
50
  return true;
50
51
  }
51
52
  function buildImportAnalysis(result) {
52
- const ast = result.parsedAst ?? parseImportProtectionAst(result.code);
53
+ const ast = result.parsedAst ?? parseAst({
54
+ code: result.code,
55
+ filename: result.filename
56
+ });
53
57
  result.parsedAst = ast;
54
58
  const importSourcesInOrder = [];
55
59
  const importSpecifierLocationIndex = /* @__PURE__ */ new Map();
@@ -170,8 +174,8 @@ function getOrCreateImportAnalysis(result) {
170
174
  function getImportSourcesFromResult(result) {
171
175
  return getOrCreateImportAnalysis(result).importSourcesInOrder;
172
176
  }
173
- function getImportSources(code) {
174
- return getImportSourcesFromResult(makeTransientResult(code));
177
+ function getImportSources(code, filename) {
178
+ return getImportSourcesFromResult(makeTransientResult(code, filename));
175
179
  }
176
180
  function getImportSpecifierLocationFromResult(result, source) {
177
181
  return getOrCreateImportAnalysis(result).importSpecifierLocationIndex.get(source) ?? -1;
@@ -179,14 +183,14 @@ function getImportSpecifierLocationFromResult(result, source) {
179
183
  function getMockExportNamesBySourceFromResult(result) {
180
184
  return getOrCreateImportAnalysis(result).mockExportNamesBySource;
181
185
  }
182
- function getMockExportNamesBySource(code) {
183
- return getMockExportNamesBySourceFromResult(makeTransientResult(code));
186
+ function getMockExportNamesBySource(code, filename) {
187
+ return getMockExportNamesBySourceFromResult(makeTransientResult(code, filename));
184
188
  }
185
189
  function getNamedExportsFromResult(result) {
186
190
  return getOrCreateImportAnalysis(result).namedExports;
187
191
  }
188
- function getNamedExports(code) {
189
- return getNamedExportsFromResult(makeTransientResult(code));
192
+ function getNamedExports(code, filename) {
193
+ return getNamedExportsFromResult(makeTransientResult(code, filename));
190
194
  }
191
195
  function isCompilerSafeBoundaryCall(call, fnNode, envType) {
192
196
  if (!call.arguments.some((arg) => arg === fnNode)) return false;
@@ -1 +1 @@
1
- {"version":3,"file":"analysis.js","names":[],"sources":["../../../src/import-protection/analysis.ts"],"sourcesContent":["import * as t from '@babel/types'\n\nimport { parseImportProtectionAst } from './ast'\nimport { buildLineIndex } from './sourceLocation'\nimport { getOrCreate } from './utils'\nimport type { LineIndex, TransformResult } from './sourceLocation'\nimport type { ParsedAst } from './ast'\n\nexport type UsagePos = { line: number; column0: number }\n\ntype BoundaryEnv = 'client' | 'server'\n\ntype ImportBindingInfo = {\n importedLocalNames: Set<string>\n memberBindingToSource: Map<string, string>\n}\n\ntype UsageCacheKey = `${BoundaryEnv | 'post'}::${string}`\n\nexport type ImportAnalysis = {\n ast: ParsedAst\n lineIndex: LineIndex\n importSourcesInOrder: Array<string>\n importSpecifierLocationIndex: Map<string, number>\n importBindingsBySource: Map<string, ImportBindingInfo>\n mockExportNamesBySource: Map<string, Array<string>>\n namedExports: Array<string>\n usageByKey: Map<UsageCacheKey, UsagePos | null>\n}\n\nfunction makeTransientResult(code: string): TransformResult {\n return {\n code,\n map: undefined,\n originalCode: undefined,\n }\n}\n\nfunction getModuleExportName(node: t.Identifier | t.StringLiteral): string {\n return t.isIdentifier(node) ? node.name : node.value\n}\n\nfunction getStringLiteralValueStart(node: t.StringLiteral): number {\n if (node.start == null) {\n return -1\n }\n\n const raw = node.extra?.raw\n if (typeof raw === 'string' && (raw.startsWith(\"'\") || raw.startsWith('\"'))) {\n return node.start + 1\n }\n\n return node.start\n}\n\nfunction isTypeOnlyImportDeclaration(node: t.ImportDeclaration): boolean {\n if (node.importKind === 'type') return true\n if (node.specifiers.length === 0) return false\n\n return node.specifiers.every(\n (specifier) =>\n t.isImportSpecifier(specifier) && specifier.importKind === 'type',\n )\n}\n\nfunction isTypeOnlyExportNamedDeclaration(\n node: t.ExportNamedDeclaration,\n): boolean {\n if (node.exportKind === 'type') return true\n if (!node.source || node.declaration || node.specifiers.length === 0) {\n return false\n }\n\n return node.specifiers.every(\n (specifier) =>\n t.isExportSpecifier(specifier) && specifier.exportKind === 'type',\n )\n}\n\nfunction collectIdentifiersFromPattern(\n pattern: t.LVal,\n add: (name: string) => void,\n): void {\n if (t.isIdentifier(pattern)) {\n add(pattern.name)\n } else if (t.isObjectPattern(pattern)) {\n for (const prop of pattern.properties) {\n if (t.isRestElement(prop)) {\n collectIdentifiersFromPattern(prop.argument as t.LVal, add)\n } else {\n collectIdentifiersFromPattern(prop.value as t.LVal, add)\n }\n }\n } else if (t.isArrayPattern(pattern)) {\n for (const elem of pattern.elements) {\n if (elem) collectIdentifiersFromPattern(elem as t.LVal, add)\n }\n } else if (t.isAssignmentPattern(pattern)) {\n collectIdentifiersFromPattern(pattern.left, add)\n } else if (t.isRestElement(pattern)) {\n collectIdentifiersFromPattern(pattern.argument as t.LVal, add)\n }\n}\n\nexport function isValidExportName(name: string): boolean {\n if (name === 'default' || name.length === 0) return false\n const first = name.charCodeAt(0)\n if (\n !(\n (first >= 65 && first <= 90) ||\n (first >= 97 && first <= 122) ||\n first === 95 ||\n first === 36\n )\n )\n return false\n for (let i = 1; i < name.length; i++) {\n const ch = name.charCodeAt(i)\n if (\n !(\n (ch >= 65 && ch <= 90) ||\n (ch >= 97 && ch <= 122) ||\n (ch >= 48 && ch <= 57) ||\n ch === 95 ||\n ch === 36\n )\n )\n return false\n }\n return true\n}\n\nfunction buildImportAnalysis(result: TransformResult): ImportAnalysis {\n const ast = result.parsedAst ?? parseImportProtectionAst(result.code)\n result.parsedAst = ast\n\n const importSourcesInOrder: Array<string> = []\n const importSpecifierLocationIndex = new Map<string, number>()\n const importBindingsBySource = new Map<string, ImportBindingInfo>()\n const mockNamesBySource = new Map<string, Set<string>>()\n const namedExports = new Set<string>()\n\n const getBindingInfo = (source: string): ImportBindingInfo =>\n getOrCreate(importBindingsBySource, source, () => ({\n importedLocalNames: new Set<string>(),\n memberBindingToSource: new Map<string, string>(),\n }))\n\n const addSpecifierLocation = (node: t.StringLiteral) => {\n importSourcesInOrder.push(node.value)\n\n const index = getStringLiteralValueStart(node)\n if (index === -1) {\n return\n }\n\n const prev = importSpecifierLocationIndex.get(node.value)\n if (prev == null || index < prev) {\n importSpecifierLocationIndex.set(node.value, index)\n }\n }\n\n const addMockName = (source: string, name: string) => {\n if (name === 'default' || name.length === 0) return\n getOrCreate(mockNamesBySource, source, () => new Set<string>()).add(name)\n }\n\n const addNamedExport = (name: string) => {\n if (name !== 'default' && name.length > 0) {\n namedExports.add(name)\n }\n }\n\n const visit = (node: t.Node): void => {\n if (t.isImportDeclaration(node)) {\n const isTypeOnly = isTypeOnlyImportDeclaration(node)\n if (!isTypeOnly) {\n addSpecifierLocation(node.source)\n const source = node.source.value\n const bindingInfo = getBindingInfo(source)\n for (const specifier of node.specifiers) {\n if (t.isImportNamespaceSpecifier(specifier)) {\n bindingInfo.importedLocalNames.add(specifier.local.name)\n bindingInfo.memberBindingToSource.set(specifier.local.name, source)\n continue\n }\n\n if (t.isImportDefaultSpecifier(specifier)) {\n bindingInfo.importedLocalNames.add(specifier.local.name)\n bindingInfo.memberBindingToSource.set(specifier.local.name, source)\n continue\n }\n\n if (!t.isImportSpecifier(specifier)) continue\n if (specifier.importKind === 'type') continue\n\n bindingInfo.importedLocalNames.add(specifier.local.name)\n const importedName = getModuleExportName(specifier.imported)\n if (importedName !== 'default') {\n addMockName(source, importedName)\n }\n }\n }\n } else if (t.isExportNamedDeclaration(node)) {\n const isTypeOnly = isTypeOnlyExportNamedDeclaration(node)\n if (!isTypeOnly && node.source && t.isStringLiteral(node.source)) {\n addSpecifierLocation(node.source)\n }\n\n if (!isTypeOnly && node.source?.value) {\n const source = node.source.value\n for (const specifier of node.specifiers) {\n if (!t.isExportSpecifier(specifier)) continue\n if (specifier.exportKind === 'type') continue\n addMockName(source, getModuleExportName(specifier.local))\n }\n }\n\n if (!isTypeOnly) {\n if (node.declaration) {\n const decl = node.declaration\n if (t.isFunctionDeclaration(decl) || t.isClassDeclaration(decl)) {\n if (decl.id?.name) addNamedExport(decl.id.name)\n } else if (t.isVariableDeclaration(decl)) {\n for (const d of decl.declarations) {\n collectIdentifiersFromPattern(d.id as t.LVal, addNamedExport)\n }\n }\n }\n\n for (const specifier of node.specifiers) {\n if (!t.isExportSpecifier(specifier)) continue\n if (specifier.exportKind === 'type') continue\n const exportedName = getModuleExportName(specifier.exported)\n addNamedExport(exportedName)\n }\n }\n } else if (t.isExportAllDeclaration(node)) {\n if (node.exportKind !== 'type') {\n addSpecifierLocation(node.source)\n }\n } else if (t.isImportExpression(node)) {\n if (t.isStringLiteral(node.source)) {\n addSpecifierLocation(node.source)\n }\n } else if (t.isCallExpression(node) && t.isImport(node.callee)) {\n const sourceNode = node.arguments[0]\n if (t.isStringLiteral(sourceNode)) {\n addSpecifierLocation(sourceNode)\n }\n } else if (\n t.isMemberExpression(node) ||\n t.isOptionalMemberExpression(node)\n ) {\n const object = node.object\n if (t.isIdentifier(object)) {\n for (const [source, bindingInfo] of importBindingsBySource) {\n if (!bindingInfo.memberBindingToSource.has(object.name)) {\n continue\n }\n\n const property = node.property\n if (!node.computed && t.isIdentifier(property)) {\n addMockName(source, property.name)\n } else if (node.computed && t.isStringLiteral(property)) {\n addMockName(source, property.value)\n }\n }\n }\n }\n\n const keys = t.VISITOR_KEYS[node.type]\n if (!keys) return\n for (const key of keys) {\n const child = (node as unknown as Record<string, unknown>)[key]\n if (Array.isArray(child)) {\n for (const item of child) {\n if (item && typeof item === 'object' && 'type' in item) {\n visit(item as t.Node)\n }\n }\n } else if (child && typeof child === 'object' && 'type' in child) {\n visit(child as t.Node)\n }\n }\n }\n\n visit(ast.program)\n\n const mockExportNamesBySource = new Map<string, Array<string>>()\n for (const [source, names] of mockNamesBySource) {\n mockExportNamesBySource.set(source, Array.from(names).sort())\n }\n\n const lineIndex = result.lineIndex ?? buildLineIndex(result.code)\n result.lineIndex = lineIndex\n\n const analysis = {\n ast,\n lineIndex,\n importSourcesInOrder,\n importSpecifierLocationIndex,\n importBindingsBySource,\n mockExportNamesBySource,\n namedExports: Array.from(namedExports).sort(),\n usageByKey: new Map(),\n }\n\n return analysis\n}\n\nexport function getOrCreateImportAnalysis(\n result: TransformResult,\n): ImportAnalysis {\n if (!result.analysis) {\n result.analysis = buildImportAnalysis(result)\n }\n\n return result.analysis\n}\n\nexport function getImportSourcesFromResult(\n result: TransformResult,\n): Array<string> {\n return getOrCreateImportAnalysis(result).importSourcesInOrder\n}\n\nexport function getImportSources(code: string): Array<string> {\n return getImportSourcesFromResult(makeTransientResult(code))\n}\n\nexport function getImportSpecifierLocationFromResult(\n result: TransformResult,\n source: string,\n): number {\n return (\n getOrCreateImportAnalysis(result).importSpecifierLocationIndex.get(\n source,\n ) ?? -1\n )\n}\n\nexport function getMockExportNamesBySourceFromResult(\n result: TransformResult,\n): Map<string, Array<string>> {\n return getOrCreateImportAnalysis(result).mockExportNamesBySource\n}\n\nexport function getMockExportNamesBySource(\n code: string,\n): Map<string, Array<string>> {\n return getMockExportNamesBySourceFromResult(makeTransientResult(code))\n}\n\nexport function getNamedExportsFromResult(\n result: TransformResult,\n): Array<string> {\n return getOrCreateImportAnalysis(result).namedExports\n}\n\nexport function getNamedExports(code: string): Array<string> {\n return getNamedExportsFromResult(makeTransientResult(code))\n}\n\nfunction isCompilerSafeBoundaryCall(\n call: t.CallExpression,\n fnNode: t.Function,\n envType: BoundaryEnv,\n): boolean {\n const directArgument = call.arguments.some((arg) => arg === fnNode)\n if (!directArgument) {\n return false\n }\n\n const callee = call.callee\n\n if (t.isIdentifier(callee)) {\n return envType === 'client'\n ? callee.name === 'createServerOnlyFn'\n : callee.name === 'createClientOnlyFn'\n }\n\n if (!t.isMemberExpression(callee) || callee.computed) {\n return false\n }\n\n if (!t.isIdentifier(callee.property)) {\n return false\n }\n\n const prop = callee.property.name\n const rootName = getCalleeRootName(callee.object)\n\n if (envType === 'client') {\n if (prop === 'handler') {\n return rootName === 'createServerFn' || /ServerFn$/.test(rootName ?? '')\n }\n\n if (prop === 'server') {\n return (\n rootName === 'createMiddleware' ||\n rootName === 'createIsomorphicFn' ||\n /Middleware$/.test(rootName ?? '')\n )\n }\n\n return false\n }\n\n if (prop === 'client') {\n return rootName === 'createIsomorphicFn'\n }\n\n return false\n}\n\nfunction getCalleeRootName(\n node: t.Expression | t.Super | t.V8IntrinsicIdentifier,\n): string | undefined {\n if (t.isIdentifier(node)) {\n return node.name\n }\n\n if (t.isCallExpression(node)) {\n return getCalleeRootName(node.callee)\n }\n\n if (t.isMemberExpression(node)) {\n return getCalleeRootName(node.object)\n }\n\n return undefined\n}\n\nfunction getBoundNamesFromPattern(pattern: t.LVal, out: Set<string>): void {\n if (t.isIdentifier(pattern)) {\n out.add(pattern.name)\n } else if (t.isObjectPattern(pattern)) {\n for (const prop of pattern.properties) {\n if (t.isRestElement(prop)) {\n getBoundNamesFromPattern(prop.argument as t.LVal, out)\n } else {\n getBoundNamesFromPattern(prop.value as t.LVal, out)\n }\n }\n } else if (t.isArrayPattern(pattern)) {\n for (const elem of pattern.elements) {\n if (elem) getBoundNamesFromPattern(elem as t.LVal, out)\n }\n } else if (t.isAssignmentPattern(pattern)) {\n getBoundNamesFromPattern(pattern.left, out)\n } else if (t.isRestElement(pattern)) {\n getBoundNamesFromPattern(pattern.argument as t.LVal, out)\n }\n}\n\nfunction addPatternBindingsIfTracked(\n pattern: t.LVal,\n tracked: Set<string>,\n out: Set<string>,\n): void {\n const names = new Set<string>()\n getBoundNamesFromPattern(pattern, names)\n for (const name of names) {\n if (tracked.has(name)) {\n out.add(name)\n }\n }\n}\n\nfunction collectHoistedVarBindings(\n node: t.Node,\n tracked: Set<string>,\n out: Set<string>,\n isRoot = true,\n): void {\n if (!isRoot && t.isFunction(node)) {\n return\n }\n\n if (t.isVariableDeclaration(node) && node.kind === 'var') {\n for (const decl of node.declarations) {\n addPatternBindingsIfTracked(decl.id as t.LVal, tracked, out)\n }\n }\n\n const keys = t.VISITOR_KEYS[node.type]\n if (!keys) return\n for (const key of keys) {\n const child = (node as unknown as Record<string, unknown>)[key]\n if (Array.isArray(child)) {\n for (const item of child) {\n if (item && typeof item === 'object' && 'type' in item) {\n collectHoistedVarBindings(item as t.Node, tracked, out, false)\n }\n }\n } else if (child && typeof child === 'object' && 'type' in child) {\n collectHoistedVarBindings(child as t.Node, tracked, out, false)\n }\n }\n}\n\nfunction collectProgramBindings(\n program: t.Program,\n tracked: Set<string>,\n): Set<string> {\n const bindings = new Set<string>()\n\n for (const node of program.body) {\n if (t.isVariableDeclaration(node)) {\n for (const decl of node.declarations) {\n addPatternBindingsIfTracked(decl.id as t.LVal, tracked, bindings)\n }\n continue\n }\n\n if (t.isFunctionDeclaration(node) || t.isClassDeclaration(node)) {\n if (node.id && tracked.has(node.id.name)) {\n bindings.add(node.id.name)\n }\n }\n }\n\n return bindings\n}\n\nfunction collectBlockBindings(\n block: t.BlockStatement,\n tracked: Set<string>,\n): Set<string> {\n const bindings = new Set<string>()\n\n for (const node of block.body) {\n if (t.isVariableDeclaration(node) && node.kind !== 'var') {\n for (const decl of node.declarations) {\n addPatternBindingsIfTracked(decl.id as t.LVal, tracked, bindings)\n }\n continue\n }\n\n if (t.isFunctionDeclaration(node) || t.isClassDeclaration(node)) {\n if (node.id && tracked.has(node.id.name)) {\n bindings.add(node.id.name)\n }\n }\n }\n\n return bindings\n}\n\nfunction collectFunctionBindings(\n fn: t.Function,\n tracked: Set<string>,\n): Set<string> {\n const bindings = new Set<string>()\n\n if (\n (t.isFunctionDeclaration(fn) || t.isFunctionExpression(fn)) &&\n fn.id &&\n tracked.has(fn.id.name)\n ) {\n bindings.add(fn.id.name)\n }\n\n for (const param of fn.params) {\n addPatternBindingsIfTracked(param as t.LVal, tracked, bindings)\n }\n\n if (t.isBlockStatement(fn.body)) {\n collectHoistedVarBindings(fn.body, tracked, bindings)\n }\n\n return bindings\n}\n\ntype UsageWalkContext = {\n parents: Array<t.Node>\n scopeStack: Array<Set<string>>\n}\n\nfunction isShadowedByScope(\n name: string,\n scopeStack: Array<Set<string>>,\n): boolean {\n for (let i = scopeStack.length - 1; i >= 0; i--) {\n if (scopeStack[i]?.has(name)) {\n return true\n }\n }\n return false\n}\n\nfunction isBindingIdentifierInParent(\n node: t.Identifier,\n parent: t.Node | undefined,\n): boolean {\n if (!parent) return false\n\n if (t.isImportSpecifier(parent) || t.isImportDefaultSpecifier(parent)) {\n return parent.local === node\n }\n if (t.isImportNamespaceSpecifier(parent)) {\n return parent.local === node\n }\n if (t.isFunctionDeclaration(parent) || t.isFunctionExpression(parent)) {\n return (\n parent.id === node || parent.params.includes(node as unknown as t.Pattern)\n )\n }\n if (t.isArrowFunctionExpression(parent)) {\n return parent.params.includes(node as unknown as t.Pattern)\n }\n if (t.isClassDeclaration(parent) || t.isClassExpression(parent)) {\n return parent.id === node\n }\n if (t.isVariableDeclarator(parent)) {\n return parent.id === node\n }\n if (t.isCatchClause(parent)) {\n return parent.param === node\n }\n\n return false\n}\n\nfunction isInsideCompilerSafeBoundaryNodes(\n parents: Array<t.Node>,\n envType: BoundaryEnv,\n): boolean {\n for (let i = parents.length - 1; i >= 0; i--) {\n const node = parents[i]!\n if (!t.isFunction(node)) {\n continue\n }\n\n const call = parents[i - 1]\n if (\n call &&\n t.isCallExpression(call) &&\n isCompilerSafeBoundaryCall(call, node, envType)\n ) {\n return true\n }\n }\n\n return false\n}\n\nfunction findUsagePosInAnalysis(\n result: TransformResult,\n source: string,\n envType?: BoundaryEnv,\n): UsagePos | undefined {\n const analysis = getOrCreateImportAnalysis(result)\n const cacheKey: UsageCacheKey = `${envType ?? 'post'}::${source}`\n if (analysis.usageByKey.has(cacheKey)) {\n return analysis.usageByKey.get(cacheKey) ?? undefined\n }\n\n const imported =\n analysis.importBindingsBySource.get(source)?.importedLocalNames\n if (!imported || imported.size === 0) {\n analysis.usageByKey.set(cacheKey, null)\n return undefined\n }\n\n let preferred: UsagePos | undefined\n let anyUsage: UsagePos | undefined\n\n const visit = (node: t.Node, ctx: UsageWalkContext): void => {\n if (preferred && anyUsage) {\n return\n }\n\n if (t.isProgram(node)) {\n const nextCtx = {\n parents: [...ctx.parents, node],\n scopeStack: [...ctx.scopeStack, collectProgramBindings(node, imported)],\n }\n for (const child of node.body) {\n visit(child, nextCtx)\n }\n return\n }\n\n if (t.isFunction(node)) {\n const functionCtx = {\n parents: [...ctx.parents, node],\n scopeStack: [\n ...ctx.scopeStack,\n collectFunctionBindings(node, imported),\n ],\n }\n\n visit(node.body, functionCtx)\n return\n }\n\n if (t.isBlockStatement(node)) {\n const nextCtx = {\n parents: [...ctx.parents, node],\n scopeStack: [...ctx.scopeStack, collectBlockBindings(node, imported)],\n }\n for (const child of node.body) {\n visit(child, nextCtx)\n }\n return\n }\n\n if (t.isCatchClause(node)) {\n const bindings = new Set<string>()\n if (node.param) {\n addPatternBindingsIfTracked(node.param as t.LVal, imported, bindings)\n }\n const nextCtx = {\n parents: [...ctx.parents, node],\n scopeStack: bindings.size\n ? [...ctx.scopeStack, bindings]\n : ctx.scopeStack,\n }\n visit(node.body, nextCtx)\n return\n }\n\n if (\n t.isForStatement(node) &&\n t.isVariableDeclaration(node.init) &&\n node.init.kind !== 'var'\n ) {\n const bindings = new Set<string>()\n for (const decl of node.init.declarations) {\n addPatternBindingsIfTracked(decl.id as t.LVal, imported, bindings)\n }\n const nextCtx = {\n parents: [...ctx.parents, node],\n scopeStack: bindings.size\n ? [...ctx.scopeStack, bindings]\n : ctx.scopeStack,\n }\n visit(node.init, nextCtx)\n if (node.test) visit(node.test, nextCtx)\n if (node.update) visit(node.update, nextCtx)\n visit(node.body, nextCtx)\n return\n }\n\n if (\n (t.isForInStatement(node) || t.isForOfStatement(node)) &&\n t.isVariableDeclaration(node.left) &&\n node.left.kind !== 'var'\n ) {\n const bindings = new Set<string>()\n for (const decl of node.left.declarations) {\n addPatternBindingsIfTracked(decl.id as t.LVal, imported, bindings)\n }\n const nextCtx = {\n parents: [...ctx.parents, node],\n scopeStack: bindings.size\n ? [...ctx.scopeStack, bindings]\n : ctx.scopeStack,\n }\n visit(node.left, nextCtx)\n visit(node.right, nextCtx)\n visit(node.body, nextCtx)\n return\n }\n\n const nextParents = [...ctx.parents, node]\n\n if (t.isIdentifier(node)) {\n const parent = ctx.parents[ctx.parents.length - 1]\n if (imported.has(node.name)) {\n if (!isBindingIdentifierInParent(node, parent)) {\n if (\n !(\n t.isObjectProperty(parent) &&\n parent.key === node &&\n !parent.computed &&\n !parent.shorthand\n ) &&\n !(\n t.isObjectMethod(parent) &&\n parent.key === node &&\n !parent.computed\n ) &&\n !(t.isExportSpecifier(parent) && parent.exported === node) &&\n !isShadowedByScope(node.name, ctx.scopeStack) &&\n !(\n envType && isInsideCompilerSafeBoundaryNodes(ctx.parents, envType)\n )\n ) {\n const loc = node.loc?.start\n if (loc) {\n const pos: UsagePos = { line: loc.line, column0: loc.column }\n const isPreferred =\n (t.isCallExpression(parent) && parent.callee === node) ||\n (t.isNewExpression(parent) && parent.callee === node) ||\n ((t.isMemberExpression(parent) ||\n t.isOptionalMemberExpression(parent)) &&\n parent.object === node)\n\n if (isPreferred) {\n preferred ||= pos\n } else {\n anyUsage ||= pos\n }\n }\n }\n }\n }\n }\n\n if (t.isImportDeclaration(node)) {\n return\n }\n\n const keys = t.VISITOR_KEYS[node.type]\n if (!keys) return\n for (const key of keys) {\n const child = (node as unknown as Record<string, unknown>)[key]\n if (Array.isArray(child)) {\n for (const item of child) {\n if (item && typeof item === 'object' && 'type' in item) {\n visit(item as t.Node, {\n parents: nextParents,\n scopeStack: ctx.scopeStack,\n })\n }\n }\n } else if (child && typeof child === 'object' && 'type' in child) {\n visit(child as t.Node, {\n parents: nextParents,\n scopeStack: ctx.scopeStack,\n })\n }\n }\n }\n\n visit(analysis.ast.program, {\n parents: [],\n scopeStack: [],\n })\n\n const pos = preferred ?? anyUsage ?? null\n analysis.usageByKey.set(cacheKey, pos)\n return pos ?? undefined\n}\n\nexport function findPostCompileUsagePosFromResult(\n result: TransformResult,\n source: string,\n): UsagePos | undefined {\n return findUsagePosInAnalysis(result, source)\n}\n\nexport function findPostCompileUsagePos(\n code: string,\n source: string,\n): UsagePos | undefined {\n return findPostCompileUsagePosFromResult(makeTransientResult(code), source)\n}\n\nexport function findOriginalUnsafeUsagePosFromResult(\n result: TransformResult,\n source: string,\n envType: BoundaryEnv,\n): UsagePos | undefined {\n return findUsagePosInAnalysis(result, source, envType)\n}\n\nexport function findOriginalUnsafeUsagePos(\n code: string,\n source: string,\n envType: BoundaryEnv,\n): UsagePos | undefined {\n return findOriginalUnsafeUsagePosFromResult(\n makeTransientResult(code),\n source,\n envType,\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"analysis.js","names":[],"sources":["../../../src/import-protection/analysis.ts"],"sourcesContent":["import * as t from '@babel/types'\nimport { parseAst } from '@tanstack/router-utils'\n\nimport { buildLineIndex } from './sourceLocation'\nimport { getOrCreate } from './utils'\nimport type { LineIndex, TransformResult } from './sourceLocation'\nimport type { ParseAstResult } from '@tanstack/router-utils'\n\nexport type UsagePos = { line: number; column0: number }\n\ntype BoundaryEnv = 'client' | 'server'\n\ntype ImportBindingInfo = {\n importedLocalNames: Set<string>\n memberBindingToSource: Map<string, string>\n}\n\ntype UsageCacheKey = `${BoundaryEnv | 'post'}::${string}`\n\nexport type ImportAnalysis = {\n ast: ParseAstResult\n lineIndex: LineIndex\n importSourcesInOrder: Array<string>\n importSpecifierLocationIndex: Map<string, number>\n importBindingsBySource: Map<string, ImportBindingInfo>\n mockExportNamesBySource: Map<string, Array<string>>\n namedExports: Array<string>\n usageByKey: Map<UsageCacheKey, UsagePos | null>\n}\n\nfunction makeTransientResult(code: string, filename?: string): TransformResult {\n return {\n code,\n filename,\n map: undefined,\n originalCode: undefined,\n }\n}\n\nfunction getModuleExportName(node: t.Identifier | t.StringLiteral): string {\n return t.isIdentifier(node) ? node.name : node.value\n}\n\nfunction getStringLiteralValueStart(node: t.StringLiteral): number {\n if (node.start == null) {\n return -1\n }\n\n const raw = node.extra?.raw\n if (typeof raw === 'string' && (raw.startsWith(\"'\") || raw.startsWith('\"'))) {\n return node.start + 1\n }\n\n return node.start\n}\n\nfunction isTypeOnlyImportDeclaration(node: t.ImportDeclaration): boolean {\n if (node.importKind === 'type') return true\n if (node.specifiers.length === 0) return false\n\n return node.specifiers.every(\n (specifier) =>\n t.isImportSpecifier(specifier) && specifier.importKind === 'type',\n )\n}\n\nfunction isTypeOnlyExportNamedDeclaration(\n node: t.ExportNamedDeclaration,\n): boolean {\n if (node.exportKind === 'type') return true\n if (!node.source || node.declaration || node.specifiers.length === 0) {\n return false\n }\n\n return node.specifiers.every(\n (specifier) =>\n t.isExportSpecifier(specifier) && specifier.exportKind === 'type',\n )\n}\n\nfunction collectIdentifiersFromPattern(\n pattern: t.LVal,\n add: (name: string) => void,\n): void {\n if (t.isIdentifier(pattern)) {\n add(pattern.name)\n } else if (t.isObjectPattern(pattern)) {\n for (const prop of pattern.properties) {\n if (t.isRestElement(prop)) {\n collectIdentifiersFromPattern(prop.argument as t.LVal, add)\n } else {\n collectIdentifiersFromPattern(prop.value as t.LVal, add)\n }\n }\n } else if (t.isArrayPattern(pattern)) {\n for (const elem of pattern.elements) {\n if (elem) collectIdentifiersFromPattern(elem as t.LVal, add)\n }\n } else if (t.isAssignmentPattern(pattern)) {\n collectIdentifiersFromPattern(pattern.left, add)\n } else if (t.isRestElement(pattern)) {\n collectIdentifiersFromPattern(pattern.argument as t.LVal, add)\n }\n}\n\nexport function isValidExportName(name: string): boolean {\n if (name === 'default' || name.length === 0) return false\n const first = name.charCodeAt(0)\n if (\n !(\n (first >= 65 && first <= 90) ||\n (first >= 97 && first <= 122) ||\n first === 95 ||\n first === 36\n )\n )\n return false\n for (let i = 1; i < name.length; i++) {\n const ch = name.charCodeAt(i)\n if (\n !(\n (ch >= 65 && ch <= 90) ||\n (ch >= 97 && ch <= 122) ||\n (ch >= 48 && ch <= 57) ||\n ch === 95 ||\n ch === 36\n )\n )\n return false\n }\n return true\n}\n\nfunction buildImportAnalysis(result: TransformResult): ImportAnalysis {\n const ast =\n result.parsedAst ??\n parseAst({ code: result.code, filename: result.filename })\n result.parsedAst = ast\n\n const importSourcesInOrder: Array<string> = []\n const importSpecifierLocationIndex = new Map<string, number>()\n const importBindingsBySource = new Map<string, ImportBindingInfo>()\n const mockNamesBySource = new Map<string, Set<string>>()\n const namedExports = new Set<string>()\n\n const getBindingInfo = (source: string): ImportBindingInfo =>\n getOrCreate(importBindingsBySource, source, () => ({\n importedLocalNames: new Set<string>(),\n memberBindingToSource: new Map<string, string>(),\n }))\n\n const addSpecifierLocation = (node: t.StringLiteral) => {\n importSourcesInOrder.push(node.value)\n\n const index = getStringLiteralValueStart(node)\n if (index === -1) {\n return\n }\n\n const prev = importSpecifierLocationIndex.get(node.value)\n if (prev == null || index < prev) {\n importSpecifierLocationIndex.set(node.value, index)\n }\n }\n\n const addMockName = (source: string, name: string) => {\n if (name === 'default' || name.length === 0) return\n getOrCreate(mockNamesBySource, source, () => new Set<string>()).add(name)\n }\n\n const addNamedExport = (name: string) => {\n if (name !== 'default' && name.length > 0) {\n namedExports.add(name)\n }\n }\n\n const visit = (node: t.Node): void => {\n if (t.isImportDeclaration(node)) {\n const isTypeOnly = isTypeOnlyImportDeclaration(node)\n if (!isTypeOnly) {\n addSpecifierLocation(node.source)\n const source = node.source.value\n const bindingInfo = getBindingInfo(source)\n for (const specifier of node.specifiers) {\n if (t.isImportNamespaceSpecifier(specifier)) {\n bindingInfo.importedLocalNames.add(specifier.local.name)\n bindingInfo.memberBindingToSource.set(specifier.local.name, source)\n continue\n }\n\n if (t.isImportDefaultSpecifier(specifier)) {\n bindingInfo.importedLocalNames.add(specifier.local.name)\n bindingInfo.memberBindingToSource.set(specifier.local.name, source)\n continue\n }\n\n if (!t.isImportSpecifier(specifier)) continue\n if (specifier.importKind === 'type') continue\n\n bindingInfo.importedLocalNames.add(specifier.local.name)\n const importedName = getModuleExportName(specifier.imported)\n if (importedName !== 'default') {\n addMockName(source, importedName)\n }\n }\n }\n } else if (t.isExportNamedDeclaration(node)) {\n const isTypeOnly = isTypeOnlyExportNamedDeclaration(node)\n if (!isTypeOnly && node.source && t.isStringLiteral(node.source)) {\n addSpecifierLocation(node.source)\n }\n\n if (!isTypeOnly && node.source?.value) {\n const source = node.source.value\n for (const specifier of node.specifiers) {\n if (!t.isExportSpecifier(specifier)) continue\n if (specifier.exportKind === 'type') continue\n addMockName(source, getModuleExportName(specifier.local))\n }\n }\n\n if (!isTypeOnly) {\n if (node.declaration) {\n const decl = node.declaration\n if (t.isFunctionDeclaration(decl) || t.isClassDeclaration(decl)) {\n if (decl.id?.name) addNamedExport(decl.id.name)\n } else if (t.isVariableDeclaration(decl)) {\n for (const d of decl.declarations) {\n collectIdentifiersFromPattern(d.id as t.LVal, addNamedExport)\n }\n }\n }\n\n for (const specifier of node.specifiers) {\n if (!t.isExportSpecifier(specifier)) continue\n if (specifier.exportKind === 'type') continue\n const exportedName = getModuleExportName(specifier.exported)\n addNamedExport(exportedName)\n }\n }\n } else if (t.isExportAllDeclaration(node)) {\n if (node.exportKind !== 'type') {\n addSpecifierLocation(node.source)\n }\n } else if (t.isImportExpression(node)) {\n if (t.isStringLiteral(node.source)) {\n addSpecifierLocation(node.source)\n }\n } else if (t.isCallExpression(node) && t.isImport(node.callee)) {\n const sourceNode = node.arguments[0]\n if (t.isStringLiteral(sourceNode)) {\n addSpecifierLocation(sourceNode)\n }\n } else if (\n t.isMemberExpression(node) ||\n t.isOptionalMemberExpression(node)\n ) {\n const object = node.object\n if (t.isIdentifier(object)) {\n for (const [source, bindingInfo] of importBindingsBySource) {\n if (!bindingInfo.memberBindingToSource.has(object.name)) {\n continue\n }\n\n const property = node.property\n if (!node.computed && t.isIdentifier(property)) {\n addMockName(source, property.name)\n } else if (node.computed && t.isStringLiteral(property)) {\n addMockName(source, property.value)\n }\n }\n }\n }\n\n const keys = t.VISITOR_KEYS[node.type]\n if (!keys) return\n for (const key of keys) {\n const child = (node as unknown as Record<string, unknown>)[key]\n if (Array.isArray(child)) {\n for (const item of child) {\n if (item && typeof item === 'object' && 'type' in item) {\n visit(item as t.Node)\n }\n }\n } else if (child && typeof child === 'object' && 'type' in child) {\n visit(child as t.Node)\n }\n }\n }\n\n visit(ast.program)\n\n const mockExportNamesBySource = new Map<string, Array<string>>()\n for (const [source, names] of mockNamesBySource) {\n mockExportNamesBySource.set(source, Array.from(names).sort())\n }\n\n const lineIndex = result.lineIndex ?? buildLineIndex(result.code)\n result.lineIndex = lineIndex\n\n const analysis = {\n ast,\n lineIndex,\n importSourcesInOrder,\n importSpecifierLocationIndex,\n importBindingsBySource,\n mockExportNamesBySource,\n namedExports: Array.from(namedExports).sort(),\n usageByKey: new Map(),\n }\n\n return analysis\n}\n\nexport function getOrCreateImportAnalysis(\n result: TransformResult,\n): ImportAnalysis {\n if (!result.analysis) {\n result.analysis = buildImportAnalysis(result)\n }\n\n return result.analysis\n}\n\nexport function getImportSourcesFromResult(\n result: TransformResult,\n): Array<string> {\n return getOrCreateImportAnalysis(result).importSourcesInOrder\n}\n\nexport function getImportSources(\n code: string,\n filename?: string,\n): Array<string> {\n return getImportSourcesFromResult(makeTransientResult(code, filename))\n}\n\nexport function getImportSpecifierLocationFromResult(\n result: TransformResult,\n source: string,\n): number {\n return (\n getOrCreateImportAnalysis(result).importSpecifierLocationIndex.get(\n source,\n ) ?? -1\n )\n}\n\nexport function getMockExportNamesBySourceFromResult(\n result: TransformResult,\n): Map<string, Array<string>> {\n return getOrCreateImportAnalysis(result).mockExportNamesBySource\n}\n\nexport function getMockExportNamesBySource(\n code: string,\n filename?: string,\n): Map<string, Array<string>> {\n return getMockExportNamesBySourceFromResult(\n makeTransientResult(code, filename),\n )\n}\n\nexport function getNamedExportsFromResult(\n result: TransformResult,\n): Array<string> {\n return getOrCreateImportAnalysis(result).namedExports\n}\n\nexport function getNamedExports(\n code: string,\n filename?: string,\n): Array<string> {\n return getNamedExportsFromResult(makeTransientResult(code, filename))\n}\n\nfunction isCompilerSafeBoundaryCall(\n call: t.CallExpression,\n fnNode: t.Function,\n envType: BoundaryEnv,\n): boolean {\n const directArgument = call.arguments.some((arg) => arg === fnNode)\n if (!directArgument) {\n return false\n }\n\n const callee = call.callee\n\n if (t.isIdentifier(callee)) {\n return envType === 'client'\n ? callee.name === 'createServerOnlyFn'\n : callee.name === 'createClientOnlyFn'\n }\n\n if (!t.isMemberExpression(callee) || callee.computed) {\n return false\n }\n\n if (!t.isIdentifier(callee.property)) {\n return false\n }\n\n const prop = callee.property.name\n const rootName = getCalleeRootName(callee.object)\n\n if (envType === 'client') {\n if (prop === 'handler') {\n return rootName === 'createServerFn' || /ServerFn$/.test(rootName ?? '')\n }\n\n if (prop === 'server') {\n return (\n rootName === 'createMiddleware' ||\n rootName === 'createIsomorphicFn' ||\n /Middleware$/.test(rootName ?? '')\n )\n }\n\n return false\n }\n\n if (prop === 'client') {\n return rootName === 'createIsomorphicFn'\n }\n\n return false\n}\n\nfunction getCalleeRootName(\n node: t.Expression | t.Super | t.V8IntrinsicIdentifier,\n): string | undefined {\n if (t.isIdentifier(node)) {\n return node.name\n }\n\n if (t.isCallExpression(node)) {\n return getCalleeRootName(node.callee)\n }\n\n if (t.isMemberExpression(node)) {\n return getCalleeRootName(node.object)\n }\n\n return undefined\n}\n\nfunction getBoundNamesFromPattern(pattern: t.LVal, out: Set<string>): void {\n if (t.isIdentifier(pattern)) {\n out.add(pattern.name)\n } else if (t.isObjectPattern(pattern)) {\n for (const prop of pattern.properties) {\n if (t.isRestElement(prop)) {\n getBoundNamesFromPattern(prop.argument as t.LVal, out)\n } else {\n getBoundNamesFromPattern(prop.value as t.LVal, out)\n }\n }\n } else if (t.isArrayPattern(pattern)) {\n for (const elem of pattern.elements) {\n if (elem) getBoundNamesFromPattern(elem as t.LVal, out)\n }\n } else if (t.isAssignmentPattern(pattern)) {\n getBoundNamesFromPattern(pattern.left, out)\n } else if (t.isRestElement(pattern)) {\n getBoundNamesFromPattern(pattern.argument as t.LVal, out)\n }\n}\n\nfunction addPatternBindingsIfTracked(\n pattern: t.LVal,\n tracked: Set<string>,\n out: Set<string>,\n): void {\n const names = new Set<string>()\n getBoundNamesFromPattern(pattern, names)\n for (const name of names) {\n if (tracked.has(name)) {\n out.add(name)\n }\n }\n}\n\nfunction collectHoistedVarBindings(\n node: t.Node,\n tracked: Set<string>,\n out: Set<string>,\n isRoot = true,\n): void {\n if (!isRoot && t.isFunction(node)) {\n return\n }\n\n if (t.isVariableDeclaration(node) && node.kind === 'var') {\n for (const decl of node.declarations) {\n addPatternBindingsIfTracked(decl.id as t.LVal, tracked, out)\n }\n }\n\n const keys = t.VISITOR_KEYS[node.type]\n if (!keys) return\n for (const key of keys) {\n const child = (node as unknown as Record<string, unknown>)[key]\n if (Array.isArray(child)) {\n for (const item of child) {\n if (item && typeof item === 'object' && 'type' in item) {\n collectHoistedVarBindings(item as t.Node, tracked, out, false)\n }\n }\n } else if (child && typeof child === 'object' && 'type' in child) {\n collectHoistedVarBindings(child as t.Node, tracked, out, false)\n }\n }\n}\n\nfunction collectProgramBindings(\n program: t.Program,\n tracked: Set<string>,\n): Set<string> {\n const bindings = new Set<string>()\n\n for (const node of program.body) {\n if (t.isVariableDeclaration(node)) {\n for (const decl of node.declarations) {\n addPatternBindingsIfTracked(decl.id as t.LVal, tracked, bindings)\n }\n continue\n }\n\n if (t.isFunctionDeclaration(node) || t.isClassDeclaration(node)) {\n if (node.id && tracked.has(node.id.name)) {\n bindings.add(node.id.name)\n }\n }\n }\n\n return bindings\n}\n\nfunction collectBlockBindings(\n block: t.BlockStatement,\n tracked: Set<string>,\n): Set<string> {\n const bindings = new Set<string>()\n\n for (const node of block.body) {\n if (t.isVariableDeclaration(node) && node.kind !== 'var') {\n for (const decl of node.declarations) {\n addPatternBindingsIfTracked(decl.id as t.LVal, tracked, bindings)\n }\n continue\n }\n\n if (t.isFunctionDeclaration(node) || t.isClassDeclaration(node)) {\n if (node.id && tracked.has(node.id.name)) {\n bindings.add(node.id.name)\n }\n }\n }\n\n return bindings\n}\n\nfunction collectFunctionBindings(\n fn: t.Function,\n tracked: Set<string>,\n): Set<string> {\n const bindings = new Set<string>()\n\n if (\n (t.isFunctionDeclaration(fn) || t.isFunctionExpression(fn)) &&\n fn.id &&\n tracked.has(fn.id.name)\n ) {\n bindings.add(fn.id.name)\n }\n\n for (const param of fn.params) {\n addPatternBindingsIfTracked(param as t.LVal, tracked, bindings)\n }\n\n if (t.isBlockStatement(fn.body)) {\n collectHoistedVarBindings(fn.body, tracked, bindings)\n }\n\n return bindings\n}\n\ntype UsageWalkContext = {\n parents: Array<t.Node>\n scopeStack: Array<Set<string>>\n}\n\nfunction isShadowedByScope(\n name: string,\n scopeStack: Array<Set<string>>,\n): boolean {\n for (let i = scopeStack.length - 1; i >= 0; i--) {\n if (scopeStack[i]?.has(name)) {\n return true\n }\n }\n return false\n}\n\nfunction isBindingIdentifierInParent(\n node: t.Identifier,\n parent: t.Node | undefined,\n): boolean {\n if (!parent) return false\n\n if (t.isImportSpecifier(parent) || t.isImportDefaultSpecifier(parent)) {\n return parent.local === node\n }\n if (t.isImportNamespaceSpecifier(parent)) {\n return parent.local === node\n }\n if (t.isFunctionDeclaration(parent) || t.isFunctionExpression(parent)) {\n return (\n parent.id === node || parent.params.includes(node as unknown as t.Pattern)\n )\n }\n if (t.isArrowFunctionExpression(parent)) {\n return parent.params.includes(node as unknown as t.Pattern)\n }\n if (t.isClassDeclaration(parent) || t.isClassExpression(parent)) {\n return parent.id === node\n }\n if (t.isVariableDeclarator(parent)) {\n return parent.id === node\n }\n if (t.isCatchClause(parent)) {\n return parent.param === node\n }\n\n return false\n}\n\nfunction isInsideCompilerSafeBoundaryNodes(\n parents: Array<t.Node>,\n envType: BoundaryEnv,\n): boolean {\n for (let i = parents.length - 1; i >= 0; i--) {\n const node = parents[i]!\n if (!t.isFunction(node)) {\n continue\n }\n\n const call = parents[i - 1]\n if (\n call &&\n t.isCallExpression(call) &&\n isCompilerSafeBoundaryCall(call, node, envType)\n ) {\n return true\n }\n }\n\n return false\n}\n\nfunction findUsagePosInAnalysis(\n result: TransformResult,\n source: string,\n envType?: BoundaryEnv,\n): UsagePos | undefined {\n const analysis = getOrCreateImportAnalysis(result)\n const cacheKey: UsageCacheKey = `${envType ?? 'post'}::${source}`\n if (analysis.usageByKey.has(cacheKey)) {\n return analysis.usageByKey.get(cacheKey) ?? undefined\n }\n\n const imported =\n analysis.importBindingsBySource.get(source)?.importedLocalNames\n if (!imported || imported.size === 0) {\n analysis.usageByKey.set(cacheKey, null)\n return undefined\n }\n\n let preferred: UsagePos | undefined\n let anyUsage: UsagePos | undefined\n\n const visit = (node: t.Node, ctx: UsageWalkContext): void => {\n if (preferred && anyUsage) {\n return\n }\n\n if (t.isProgram(node)) {\n const nextCtx = {\n parents: [...ctx.parents, node],\n scopeStack: [...ctx.scopeStack, collectProgramBindings(node, imported)],\n }\n for (const child of node.body) {\n visit(child, nextCtx)\n }\n return\n }\n\n if (t.isFunction(node)) {\n const functionCtx = {\n parents: [...ctx.parents, node],\n scopeStack: [\n ...ctx.scopeStack,\n collectFunctionBindings(node, imported),\n ],\n }\n\n visit(node.body, functionCtx)\n return\n }\n\n if (t.isBlockStatement(node)) {\n const nextCtx = {\n parents: [...ctx.parents, node],\n scopeStack: [...ctx.scopeStack, collectBlockBindings(node, imported)],\n }\n for (const child of node.body) {\n visit(child, nextCtx)\n }\n return\n }\n\n if (t.isCatchClause(node)) {\n const bindings = new Set<string>()\n if (node.param) {\n addPatternBindingsIfTracked(node.param as t.LVal, imported, bindings)\n }\n const nextCtx = {\n parents: [...ctx.parents, node],\n scopeStack: bindings.size\n ? [...ctx.scopeStack, bindings]\n : ctx.scopeStack,\n }\n visit(node.body, nextCtx)\n return\n }\n\n if (\n t.isForStatement(node) &&\n t.isVariableDeclaration(node.init) &&\n node.init.kind !== 'var'\n ) {\n const bindings = new Set<string>()\n for (const decl of node.init.declarations) {\n addPatternBindingsIfTracked(decl.id as t.LVal, imported, bindings)\n }\n const nextCtx = {\n parents: [...ctx.parents, node],\n scopeStack: bindings.size\n ? [...ctx.scopeStack, bindings]\n : ctx.scopeStack,\n }\n visit(node.init, nextCtx)\n if (node.test) visit(node.test, nextCtx)\n if (node.update) visit(node.update, nextCtx)\n visit(node.body, nextCtx)\n return\n }\n\n if (\n (t.isForInStatement(node) || t.isForOfStatement(node)) &&\n t.isVariableDeclaration(node.left) &&\n node.left.kind !== 'var'\n ) {\n const bindings = new Set<string>()\n for (const decl of node.left.declarations) {\n addPatternBindingsIfTracked(decl.id as t.LVal, imported, bindings)\n }\n const nextCtx = {\n parents: [...ctx.parents, node],\n scopeStack: bindings.size\n ? [...ctx.scopeStack, bindings]\n : ctx.scopeStack,\n }\n visit(node.left, nextCtx)\n visit(node.right, nextCtx)\n visit(node.body, nextCtx)\n return\n }\n\n const nextParents = [...ctx.parents, node]\n\n if (t.isIdentifier(node)) {\n const parent = ctx.parents[ctx.parents.length - 1]\n if (imported.has(node.name)) {\n if (!isBindingIdentifierInParent(node, parent)) {\n if (\n !(\n t.isObjectProperty(parent) &&\n parent.key === node &&\n !parent.computed &&\n !parent.shorthand\n ) &&\n !(\n t.isObjectMethod(parent) &&\n parent.key === node &&\n !parent.computed\n ) &&\n !(t.isExportSpecifier(parent) && parent.exported === node) &&\n !isShadowedByScope(node.name, ctx.scopeStack) &&\n !(\n envType && isInsideCompilerSafeBoundaryNodes(ctx.parents, envType)\n )\n ) {\n const loc = node.loc?.start\n if (loc) {\n const pos: UsagePos = { line: loc.line, column0: loc.column }\n const isPreferred =\n (t.isCallExpression(parent) && parent.callee === node) ||\n (t.isNewExpression(parent) && parent.callee === node) ||\n ((t.isMemberExpression(parent) ||\n t.isOptionalMemberExpression(parent)) &&\n parent.object === node)\n\n if (isPreferred) {\n preferred ||= pos\n } else {\n anyUsage ||= pos\n }\n }\n }\n }\n }\n }\n\n if (t.isImportDeclaration(node)) {\n return\n }\n\n const keys = t.VISITOR_KEYS[node.type]\n if (!keys) return\n for (const key of keys) {\n const child = (node as unknown as Record<string, unknown>)[key]\n if (Array.isArray(child)) {\n for (const item of child) {\n if (item && typeof item === 'object' && 'type' in item) {\n visit(item as t.Node, {\n parents: nextParents,\n scopeStack: ctx.scopeStack,\n })\n }\n }\n } else if (child && typeof child === 'object' && 'type' in child) {\n visit(child as t.Node, {\n parents: nextParents,\n scopeStack: ctx.scopeStack,\n })\n }\n }\n }\n\n visit(analysis.ast.program, {\n parents: [],\n scopeStack: [],\n })\n\n const pos = preferred ?? anyUsage ?? null\n analysis.usageByKey.set(cacheKey, pos)\n return pos ?? undefined\n}\n\nexport function findPostCompileUsagePosFromResult(\n result: TransformResult,\n source: string,\n): UsagePos | undefined {\n return findUsagePosInAnalysis(result, source)\n}\n\nexport function findPostCompileUsagePos(\n code: string,\n source: string,\n): UsagePos | undefined {\n return findPostCompileUsagePosFromResult(makeTransientResult(code), source)\n}\n\nexport function findOriginalUnsafeUsagePosFromResult(\n result: TransformResult,\n source: string,\n envType: BoundaryEnv,\n): UsagePos | undefined {\n return findUsagePosInAnalysis(result, source, envType)\n}\n\nexport function findOriginalUnsafeUsagePos(\n code: string,\n source: string,\n envType: BoundaryEnv,\n): UsagePos | undefined {\n return findOriginalUnsafeUsagePosFromResult(\n makeTransientResult(code),\n source,\n envType,\n )\n}\n"],"mappings":"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"}
@@ -1,7 +1,6 @@
1
1
  import { MOCK_MODULE_ID } from "./constants.js";
2
- import { parseImportProtectionAst } from "./ast.js";
3
2
  import * as t from "@babel/types";
4
- import { generateFromAst } from "@tanstack/router-utils";
3
+ import { generateFromAst, parseAst } from "@tanstack/router-utils";
5
4
  //#region src/import-protection/rewrite.ts
6
5
  function getModuleExportName(node) {
7
6
  return t.isIdentifier(node) ? node.name : node.value;
@@ -47,7 +46,10 @@ function createInternalReexportVarName(localName, mockIndex, usedNames) {
47
46
  * export { x as y } from 'denied' -> export const y = mock.x
48
47
  */
49
48
  function rewriteDeniedImports(code, id, deniedSources, getMockModuleId = () => MOCK_MODULE_ID) {
50
- return rewriteDeniedImportsFromAst(parseImportProtectionAst(code), id, deniedSources, getMockModuleId);
49
+ return rewriteDeniedImportsFromAst(parseAst({
50
+ code,
51
+ filename: id
52
+ }), id, deniedSources, getMockModuleId);
51
53
  }
52
54
  function rewriteDeniedImportsFromAst(ast, id, deniedSources, getMockModuleId = () => MOCK_MODULE_ID) {
53
55
  let modified = false;
@@ -1 +1 @@
1
- {"version":3,"file":"rewrite.js","names":[],"sources":["../../../src/import-protection/rewrite.ts"],"sourcesContent":["import * as t from '@babel/types'\nimport { generateFromAst } from '@tanstack/router-utils'\n\nimport { parseImportProtectionAst } from './ast'\nimport { MOCK_MODULE_ID } from './constants'\nimport type { ParsedAst } from './ast'\nimport type { SourceMapLike } from './sourceLocation'\n\nfunction getModuleExportName(node: t.Identifier | t.StringLiteral): string {\n return t.isIdentifier(node) ? node.name : node.value\n}\n\nfunction toMemberExpressionProperty(name: string): {\n property: t.Identifier | t.StringLiteral\n computed: boolean\n} {\n return t.isValidIdentifier(name)\n ? { property: t.identifier(name), computed: false }\n : { property: t.stringLiteral(name), computed: true }\n}\n\nfunction toModuleExportNameNode(name: string): t.Identifier | t.StringLiteral {\n return t.isValidIdentifier(name) ? t.identifier(name) : t.stringLiteral(name)\n}\n\nfunction createInternalReexportVarName(\n localName: string,\n mockIndex: number,\n usedNames: Set<string>,\n): string {\n const baseName = t.isValidIdentifier(localName)\n ? `__tss_reexport_${localName}`\n : `__tss_reexport_${mockIndex}`\n\n let candidate = baseName\n let suffix = 0\n while (usedNames.has(candidate)) {\n suffix++\n candidate = `${baseName}_${suffix}`\n }\n\n usedNames.add(candidate)\n return candidate\n}\n\n/**\n * Rewrite static imports/re-exports from denied sources using Babel AST transforms.\n *\n * Transforms:\n * import { a as b, c } from 'denied'\n * Into:\n * import __tss_deny_0 from 'tanstack-start-import-protection:mock'\n * const b = __tss_deny_0.a\n * const c = __tss_deny_0.c\n *\n * Also handles:\n * import def from 'denied' -> import def from mock\n * import * as ns from 'denied' -> import ns from mock\n * export { x } from 'denied' -> export const x = mock.x\n * export * from 'denied' -> removed\n * export { x as y } from 'denied' -> export const y = mock.x\n */\nexport function rewriteDeniedImports(\n code: string,\n id: string,\n deniedSources: Set<string>,\n getMockModuleId: (source: string) => string = () => MOCK_MODULE_ID,\n): { code: string; map?: SourceMapLike } | undefined {\n return rewriteDeniedImportsFromAst(\n parseImportProtectionAst(code),\n id,\n deniedSources,\n getMockModuleId,\n )\n}\n\nfunction rewriteDeniedImportsFromAst(\n ast: ParsedAst,\n id: string,\n deniedSources: Set<string>,\n getMockModuleId: (source: string) => string = () => MOCK_MODULE_ID,\n): { code: string; map?: SourceMapLike } | undefined {\n let modified = false\n let mockCounter = 0\n\n // Walk program body in reverse so splice indices stay valid\n for (let i = ast.program.body.length - 1; i >= 0; i--) {\n const node = ast.program.body[i]!\n\n if (t.isImportDeclaration(node)) {\n if (node.importKind === 'type') continue\n if (!deniedSources.has(node.source.value)) continue\n\n const mockVar = `__tss_deny_${mockCounter++}`\n const replacements: Array<t.Statement> = []\n\n replacements.push(\n t.importDeclaration(\n [t.importDefaultSpecifier(t.identifier(mockVar))],\n t.stringLiteral(getMockModuleId(node.source.value)),\n ),\n )\n\n for (const specifier of node.specifiers) {\n if (\n t.isImportDefaultSpecifier(specifier) ||\n t.isImportNamespaceSpecifier(specifier)\n ) {\n replacements.push(\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier(specifier.local.name),\n t.identifier(mockVar),\n ),\n ]),\n )\n } else if (t.isImportSpecifier(specifier)) {\n if (specifier.importKind === 'type') continue\n const importedName = getModuleExportName(specifier.imported)\n const memberProperty = toMemberExpressionProperty(importedName)\n replacements.push(\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier(specifier.local.name),\n t.memberExpression(\n t.identifier(mockVar),\n memberProperty.property,\n memberProperty.computed,\n ),\n ),\n ]),\n )\n }\n }\n\n ast.program.body.splice(i, 1, ...replacements)\n modified = true\n continue\n }\n\n if (t.isExportNamedDeclaration(node) && node.source) {\n if (node.exportKind === 'type') continue\n if (!deniedSources.has(node.source.value)) continue\n\n const mockIndex = mockCounter++\n const mockVar = `__tss_deny_${mockIndex}`\n const replacements: Array<t.Statement> = []\n\n replacements.push(\n t.importDeclaration(\n [t.importDefaultSpecifier(t.identifier(mockVar))],\n t.stringLiteral(getMockModuleId(node.source.value)),\n ),\n )\n const usedInternalVars = new Set<string>()\n const exportSpecifiers: Array<{\n localName: string\n exportedName: string\n }> = []\n for (const specifier of node.specifiers) {\n if (t.isExportSpecifier(specifier)) {\n if (specifier.exportKind === 'type') continue\n const localName = getModuleExportName(specifier.local)\n const exportedName = getModuleExportName(specifier.exported)\n const memberProperty = toMemberExpressionProperty(localName)\n\n const internalVar = createInternalReexportVarName(\n localName,\n mockIndex,\n usedInternalVars,\n )\n replacements.push(\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier(internalVar),\n t.memberExpression(\n t.identifier(mockVar),\n memberProperty.property,\n memberProperty.computed,\n ),\n ),\n ]),\n )\n exportSpecifiers.push({ localName: internalVar, exportedName })\n }\n }\n\n if (exportSpecifiers.length > 0) {\n replacements.push(\n t.exportNamedDeclaration(\n null,\n exportSpecifiers.map((s) =>\n t.exportSpecifier(\n t.identifier(s.localName),\n toModuleExportNameNode(s.exportedName),\n ),\n ),\n ),\n )\n }\n\n ast.program.body.splice(i, 1, ...replacements)\n modified = true\n continue\n }\n\n if (t.isExportAllDeclaration(node)) {\n if (node.exportKind === 'type') continue\n if (!deniedSources.has(node.source.value)) continue\n\n ast.program.body.splice(i, 1)\n modified = true\n continue\n }\n }\n\n if (!modified) return undefined\n\n const result = generateFromAst(ast, {\n sourceMaps: true,\n sourceFileName: id,\n filename: id,\n })\n\n return {\n code: result.code,\n ...(result.map ? { map: result.map as SourceMapLike } : {}),\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"rewrite.js","names":[],"sources":["../../../src/import-protection/rewrite.ts"],"sourcesContent":["import * as t from '@babel/types'\nimport { generateFromAst, parseAst } from '@tanstack/router-utils'\n\nimport { MOCK_MODULE_ID } from './constants'\nimport type { SourceMapLike } from './sourceLocation'\nimport type { ParseAstResult } from '@tanstack/router-utils'\n\nfunction getModuleExportName(node: t.Identifier | t.StringLiteral): string {\n return t.isIdentifier(node) ? node.name : node.value\n}\n\nfunction toMemberExpressionProperty(name: string): {\n property: t.Identifier | t.StringLiteral\n computed: boolean\n} {\n return t.isValidIdentifier(name)\n ? { property: t.identifier(name), computed: false }\n : { property: t.stringLiteral(name), computed: true }\n}\n\nfunction toModuleExportNameNode(name: string): t.Identifier | t.StringLiteral {\n return t.isValidIdentifier(name) ? t.identifier(name) : t.stringLiteral(name)\n}\n\nfunction createInternalReexportVarName(\n localName: string,\n mockIndex: number,\n usedNames: Set<string>,\n): string {\n const baseName = t.isValidIdentifier(localName)\n ? `__tss_reexport_${localName}`\n : `__tss_reexport_${mockIndex}`\n\n let candidate = baseName\n let suffix = 0\n while (usedNames.has(candidate)) {\n suffix++\n candidate = `${baseName}_${suffix}`\n }\n\n usedNames.add(candidate)\n return candidate\n}\n\n/**\n * Rewrite static imports/re-exports from denied sources using Babel AST transforms.\n *\n * Transforms:\n * import { a as b, c } from 'denied'\n * Into:\n * import __tss_deny_0 from 'tanstack-start-import-protection:mock'\n * const b = __tss_deny_0.a\n * const c = __tss_deny_0.c\n *\n * Also handles:\n * import def from 'denied' -> import def from mock\n * import * as ns from 'denied' -> import ns from mock\n * export { x } from 'denied' -> export const x = mock.x\n * export * from 'denied' -> removed\n * export { x as y } from 'denied' -> export const y = mock.x\n */\nexport function rewriteDeniedImports(\n code: string,\n id: string,\n deniedSources: Set<string>,\n getMockModuleId: (source: string) => string = () => MOCK_MODULE_ID,\n): { code: string; map?: SourceMapLike } | undefined {\n return rewriteDeniedImportsFromAst(\n parseAst({ code, filename: id }),\n id,\n deniedSources,\n getMockModuleId,\n )\n}\n\nfunction rewriteDeniedImportsFromAst(\n ast: ParseAstResult,\n id: string,\n deniedSources: Set<string>,\n getMockModuleId: (source: string) => string = () => MOCK_MODULE_ID,\n): { code: string; map?: SourceMapLike } | undefined {\n let modified = false\n let mockCounter = 0\n\n // Walk program body in reverse so splice indices stay valid\n for (let i = ast.program.body.length - 1; i >= 0; i--) {\n const node = ast.program.body[i]!\n\n if (t.isImportDeclaration(node)) {\n if (node.importKind === 'type') continue\n if (!deniedSources.has(node.source.value)) continue\n\n const mockVar = `__tss_deny_${mockCounter++}`\n const replacements: Array<t.Statement> = []\n\n replacements.push(\n t.importDeclaration(\n [t.importDefaultSpecifier(t.identifier(mockVar))],\n t.stringLiteral(getMockModuleId(node.source.value)),\n ),\n )\n\n for (const specifier of node.specifiers) {\n if (\n t.isImportDefaultSpecifier(specifier) ||\n t.isImportNamespaceSpecifier(specifier)\n ) {\n replacements.push(\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier(specifier.local.name),\n t.identifier(mockVar),\n ),\n ]),\n )\n } else if (t.isImportSpecifier(specifier)) {\n if (specifier.importKind === 'type') continue\n const importedName = getModuleExportName(specifier.imported)\n const memberProperty = toMemberExpressionProperty(importedName)\n replacements.push(\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier(specifier.local.name),\n t.memberExpression(\n t.identifier(mockVar),\n memberProperty.property,\n memberProperty.computed,\n ),\n ),\n ]),\n )\n }\n }\n\n ast.program.body.splice(i, 1, ...replacements)\n modified = true\n continue\n }\n\n if (t.isExportNamedDeclaration(node) && node.source) {\n if (node.exportKind === 'type') continue\n if (!deniedSources.has(node.source.value)) continue\n\n const mockIndex = mockCounter++\n const mockVar = `__tss_deny_${mockIndex}`\n const replacements: Array<t.Statement> = []\n\n replacements.push(\n t.importDeclaration(\n [t.importDefaultSpecifier(t.identifier(mockVar))],\n t.stringLiteral(getMockModuleId(node.source.value)),\n ),\n )\n const usedInternalVars = new Set<string>()\n const exportSpecifiers: Array<{\n localName: string\n exportedName: string\n }> = []\n for (const specifier of node.specifiers) {\n if (t.isExportSpecifier(specifier)) {\n if (specifier.exportKind === 'type') continue\n const localName = getModuleExportName(specifier.local)\n const exportedName = getModuleExportName(specifier.exported)\n const memberProperty = toMemberExpressionProperty(localName)\n\n const internalVar = createInternalReexportVarName(\n localName,\n mockIndex,\n usedInternalVars,\n )\n replacements.push(\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier(internalVar),\n t.memberExpression(\n t.identifier(mockVar),\n memberProperty.property,\n memberProperty.computed,\n ),\n ),\n ]),\n )\n exportSpecifiers.push({ localName: internalVar, exportedName })\n }\n }\n\n if (exportSpecifiers.length > 0) {\n replacements.push(\n t.exportNamedDeclaration(\n null,\n exportSpecifiers.map((s) =>\n t.exportSpecifier(\n t.identifier(s.localName),\n toModuleExportNameNode(s.exportedName),\n ),\n ),\n ),\n )\n }\n\n ast.program.body.splice(i, 1, ...replacements)\n modified = true\n continue\n }\n\n if (t.isExportAllDeclaration(node)) {\n if (node.exportKind === 'type') continue\n if (!deniedSources.has(node.source.value)) continue\n\n ast.program.body.splice(i, 1)\n modified = true\n continue\n }\n }\n\n if (!modified) return undefined\n\n const result = generateFromAst(ast, {\n sourceMaps: true,\n sourceFileName: id,\n filename: id,\n })\n\n return {\n code: result.code,\n ...(result.map ? { map: result.map as SourceMapLike } : {}),\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { ImportAnalysis } from './analysis.js';
2
- import { ParsedAst } from './ast.js';
3
2
  import { Loc } from './trace.js';
3
+ import { ParseAstResult } from '@tanstack/router-utils';
4
4
  /**
5
5
  * Minimal source-map shape used throughout the import-protection plugin.
6
6
  */
@@ -15,12 +15,13 @@ export interface SourceMapLike {
15
15
  }
16
16
  export interface TransformResult {
17
17
  code: string;
18
+ filename?: string;
18
19
  map: SourceMapLike | undefined;
19
20
  originalCode: string | undefined;
20
21
  originalResult?: TransformResult;
21
22
  /** Precomputed line index for `code` (index → line/col). */
22
23
  lineIndex?: LineIndex;
23
- parsedAst?: ParsedAst;
24
+ parsedAst?: ParseAstResult;
24
25
  analysis?: ImportAnalysis;
25
26
  }
26
27
  /**
@@ -168,6 +168,7 @@ function getOrCreateOriginalTransformResult(result) {
168
168
  if (!result.originalCode) return;
169
169
  if (!result.originalResult) result.originalResult = {
170
170
  code: result.originalCode,
171
+ filename: result.filename,
171
172
  map: void 0,
172
173
  originalCode: result.originalCode
173
174
  };
@@ -1 +1 @@
1
- {"version":3,"file":"sourceLocation.js","names":[],"sources":["../../../src/import-protection/sourceLocation.ts"],"sourcesContent":["import { SourceMapConsumer } from 'source-map'\nimport * as path from 'pathe'\n\nimport {\n findOriginalUnsafeUsagePosFromResult,\n findPostCompileUsagePosFromResult,\n getImportSpecifierLocationFromResult,\n} from './analysis'\nimport { getOrCreate, normalizeFilePath } from './utils'\nimport type { ImportAnalysis } from './analysis'\nimport type { ParsedAst } from './ast'\nimport type { Loc } from './trace'\nimport type { RawSourceMap } from 'source-map'\n\n// Source-map type compatible with both Rollup's SourceMap and source-map's\n// RawSourceMap. Structural type avoids version: number vs string mismatch.\n\n/**\n * Minimal source-map shape used throughout the import-protection plugin.\n */\nexport interface SourceMapLike {\n file?: string\n sourceRoot?: string\n version: number | string\n sources: Array<string>\n names: Array<string>\n sourcesContent?: Array<string | null>\n mappings: string\n}\n\n// Transform result provider (replaces ctx.load() which doesn't work in dev)\nexport interface TransformResult {\n code: string\n map: SourceMapLike | undefined\n originalCode: string | undefined\n originalResult?: TransformResult\n /** Precomputed line index for `code` (index → line/col). */\n lineIndex?: LineIndex\n parsedAst?: ParsedAst\n analysis?: ImportAnalysis\n}\n\n/**\n * Provides the transformed code and composed sourcemap for a module.\n *\n * Populated from a late-running transform hook. By the time `resolveId`\n * fires for an import, the importer has already been fully transformed.\n */\nexport interface TransformResultProvider {\n getTransformResult: (id: string) => TransformResult | undefined\n}\n\nexport interface ImportSpecifierLocationIndex {\n find: FindImportSpecifierLocationIndex\n}\n\n// Index → line/column conversion\n\nexport type LineIndex = {\n offsets: Array<number>\n}\n\nexport function buildLineIndex(code: string): LineIndex {\n const offsets: Array<number> = [0]\n for (let i = 0; i < code.length; i++) {\n if (code.charCodeAt(i) === 10) {\n offsets.push(i + 1)\n }\n }\n return { offsets }\n}\n\nfunction upperBound(values: Array<number>, x: number): number {\n let lo = 0\n let hi = values.length\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if (values[mid]! <= x) lo = mid + 1\n else hi = mid\n }\n return lo\n}\n\nfunction indexToLineColWithIndex(\n lineIndex: LineIndex,\n idx: number,\n): { line: number; column0: number } {\n const offsets = lineIndex.offsets\n const ub = upperBound(offsets, idx)\n const lineIdx = Math.max(0, ub - 1)\n const line = lineIdx + 1\n\n const lineStart = offsets[lineIdx] ?? 0\n return { line, column0: Math.max(0, idx - lineStart) }\n}\n\nexport function indexToLineColumn(\n lineIndex: LineIndex,\n idx: number,\n): { line: number; column: number } {\n const { line, column0 } = indexToLineColWithIndex(lineIndex, idx)\n return {\n line,\n column: column0 + 1,\n }\n}\n\nexport function normalizeSourceMap(map: SourceMapLike | null | undefined):\n | {\n version: number\n file: string\n sourceRoot?: string\n sources: Array<string>\n names: Array<string>\n sourcesContent?: Array<string>\n mappings: string\n }\n | undefined {\n if (!map) {\n return undefined\n }\n\n return {\n ...map,\n version: Number(map.version),\n file: map.file ?? '',\n names: Array.isArray(map.names) ? map.names : [],\n sourcesContent:\n map.sourcesContent?.map((value) => value ?? '') ?? undefined,\n }\n}\n\n/**\n * Pick the most-likely original source text for `importerFile` from\n * a sourcemap that may contain multiple sources.\n */\nexport function pickOriginalCodeFromSourcesContent(\n map: SourceMapLike | undefined,\n importerFile: string,\n root: string,\n): string | undefined {\n if (!map?.sourcesContent || map.sources.length === 0) {\n return undefined\n }\n\n const file = normalizeFilePath(importerFile)\n const sourceRoot = map.sourceRoot\n const fileSeg = file.split('/').filter(Boolean)\n\n const resolveBase = sourceRoot ? path.resolve(root, sourceRoot) : root\n\n let bestIdx = -1\n let bestScore = -1\n\n for (let i = 0; i < map.sources.length; i++) {\n const content = map.sourcesContent[i]\n if (typeof content !== 'string') continue\n\n const src = map.sources[i] ?? ''\n\n const normalizedSrc = normalizeFilePath(src)\n if (normalizedSrc === file) {\n return content\n }\n\n let resolved: string\n if (!src) {\n resolved = ''\n } else if (path.isAbsolute(src)) {\n resolved = normalizeFilePath(src)\n } else {\n resolved = normalizeFilePath(path.resolve(resolveBase, src))\n }\n if (resolved === file) {\n return content\n }\n\n // Count matching path segments from the end.\n const normalizedSrcSeg = normalizedSrc.split('/').filter(Boolean)\n const resolvedSeg =\n resolved !== normalizedSrc\n ? resolved.split('/').filter(Boolean)\n : normalizedSrcSeg\n const score = Math.max(\n segmentSuffixScore(normalizedSrcSeg, fileSeg),\n segmentSuffixScore(resolvedSeg, fileSeg),\n )\n\n if (score > bestScore) {\n bestScore = score\n bestIdx = i\n }\n }\n\n if (bestIdx !== -1 && bestScore >= 1) {\n return map.sourcesContent[bestIdx] ?? undefined\n }\n\n return map.sourcesContent[0] ?? undefined\n}\n\n/** Count matching path segments from the end of `aSeg` against `bSeg`. */\nfunction segmentSuffixScore(aSeg: Array<string>, bSeg: Array<string>): number {\n let score = 0\n for (\n let i = aSeg.length - 1, j = bSeg.length - 1;\n i >= 0 && j >= 0;\n i--, j--\n ) {\n if (aSeg[i] !== bSeg[j]) break\n score++\n }\n return score\n}\n\nasync function mapGeneratedToOriginal(\n map: SourceMapLike | undefined,\n generated: { line: number; column0: number },\n fallbackFile: string,\n): Promise<Loc> {\n const fallback: Loc = {\n file: fallbackFile,\n line: generated.line,\n column: generated.column0 + 1,\n }\n\n if (!map) {\n return fallback\n }\n\n const consumer = await getSourceMapConsumer(map)\n if (!consumer) return fallback\n\n try {\n const orig = consumer.originalPositionFor({\n line: generated.line,\n column: generated.column0,\n })\n if (orig.line != null && orig.column != null) {\n return {\n file: orig.source ? normalizeFilePath(orig.source) : fallbackFile,\n line: orig.line,\n column: orig.column + 1,\n }\n }\n } catch {\n // Malformed sourcemap\n }\n\n return fallback\n}\n\nconst consumerCache = new WeakMap<object, Promise<SourceMapConsumer | null>>()\n\nfunction toRawSourceMap(map: SourceMapLike): RawSourceMap {\n return {\n ...map,\n file: map.file ?? '',\n version: Number(map.version),\n sourcesContent: map.sourcesContent?.map((s) => s ?? '') ?? [],\n }\n}\n\nasync function getSourceMapConsumer(\n map: SourceMapLike,\n): Promise<SourceMapConsumer | null> {\n const cached = consumerCache.get(map)\n if (cached) return cached\n\n const promise = (async () => {\n try {\n return await new SourceMapConsumer(toRawSourceMap(map))\n } catch {\n return null\n }\n })()\n\n consumerCache.set(map, promise)\n return promise\n}\n\nexport type ImportLocEntry = { file?: string; line: number; column: number }\n\n/**\n * Cache for import statement locations with reverse index for O(1)\n * invalidation by file. Keys: `${importerFile}::${source}`.\n */\nexport class ImportLocCache {\n private cache = new Map<string, ImportLocEntry | null>()\n private reverseIndex = new Map<string, Set<string>>()\n\n has(key: string): boolean {\n return this.cache.has(key)\n }\n\n get(key: string): ImportLocEntry | null | undefined {\n return this.cache.get(key)\n }\n\n set(key: string, value: ImportLocEntry | null): void {\n this.cache.set(key, value)\n const file = key.slice(0, key.indexOf('::'))\n getOrCreate(this.reverseIndex, file, () => new Set()).add(key)\n }\n\n clear(): void {\n this.cache.clear()\n this.reverseIndex.clear()\n }\n\n /** Remove all cache entries where the importer matches `file`. */\n deleteByFile(file: string): void {\n const keys = this.reverseIndex.get(file)\n if (keys) {\n for (const key of keys) {\n this.cache.delete(key)\n }\n this.reverseIndex.delete(file)\n }\n }\n}\n\nexport type FindImportSpecifierLocationIndex = (\n result: TransformResult,\n source: string,\n) => number\n\nexport function getOrCreateOriginalTransformResult(\n result: TransformResult,\n): TransformResult | undefined {\n if (!result.originalCode) {\n return undefined\n }\n\n if (!result.originalResult) {\n result.originalResult = {\n code: result.originalCode,\n map: undefined,\n originalCode: result.originalCode,\n }\n }\n\n return result.originalResult\n}\n\nexport function createImportSpecifierLocationIndex(): ImportSpecifierLocationIndex {\n return {\n find(result: TransformResult, source: string): number {\n if (!result.code.includes(source)) {\n return -1\n }\n\n return getImportSpecifierLocationFromResult(result, source)\n },\n }\n}\n\n/**\n * Find the location of an import statement in a transformed module\n * by searching the post-transform code and mapping back via sourcemap.\n * Results are cached in `importLocCache`.\n */\nexport async function findImportStatementLocationFromTransformed(\n provider: TransformResultProvider,\n importerId: string,\n source: string,\n importLocCache: ImportLocCache,\n findImportSpecifierLocationIndex: FindImportSpecifierLocationIndex,\n): Promise<Loc | undefined> {\n const importerFile = normalizeFilePath(importerId)\n const cacheKey = `${importerFile}::${source}`\n if (importLocCache.has(cacheKey)) {\n return importLocCache.get(cacheKey) ?? undefined\n }\n\n try {\n const res = provider.getTransformResult(importerId)\n if (!res) {\n importLocCache.set(cacheKey, null)\n return undefined\n }\n\n const { map } = res\n\n const lineIndex =\n res.lineIndex ?? (res.lineIndex = buildLineIndex(res.code))\n\n const idx = findImportSpecifierLocationIndex(res, source)\n if (idx === -1) {\n importLocCache.set(cacheKey, null)\n return undefined\n }\n\n const generated = indexToLineColWithIndex(lineIndex, idx)\n const loc = await mapGeneratedToOriginal(map, generated, importerFile)\n importLocCache.set(cacheKey, loc)\n return loc\n } catch {\n importLocCache.set(cacheKey, null)\n return undefined\n }\n}\n\n/**\n * Find the first post-compile usage location for a denied import specifier.\n * Best-effort: searches transformed code for non-import uses of imported\n * bindings and maps back to original source via sourcemap.\n */\nexport async function findPostCompileUsageLocation(\n provider: TransformResultProvider,\n importerId: string,\n source: string,\n): Promise<Loc | undefined> {\n try {\n const importerFile = normalizeFilePath(importerId)\n const res = provider.getTransformResult(importerId)\n if (!res) return undefined\n const { code, map } = res\n\n if (!res.lineIndex) {\n res.lineIndex = buildLineIndex(code)\n }\n\n const pos = findPostCompileUsagePosFromResult(res, source)\n if (!pos) return undefined\n\n return await mapGeneratedToOriginal(map, pos, importerFile)\n } catch {\n return undefined\n }\n}\n\n/**\n * Best-effort original-source usage lookup for cases where a later transform\n * removes or rewrites the import from emitted code but preserves the original\n * source in `sourcesContent`.\n */\nexport function findOriginalUsageLocation(\n provider: TransformResultProvider,\n importerId: string,\n source: string,\n envType?: 'client' | 'server',\n): Loc | undefined {\n try {\n const importerFile = normalizeFilePath(importerId)\n const res = provider.getTransformResult(importerId)\n if (!res) return undefined\n const originalResult = getOrCreateOriginalTransformResult(res)\n if (!originalResult) return undefined\n\n const pos = envType\n ? findOriginalUnsafeUsagePosFromResult(originalResult, source, envType)\n : findPostCompileUsagePosFromResult(originalResult, source)\n if (!pos) return undefined\n\n return {\n file: importerFile,\n line: pos.line,\n column: pos.column0 + 1,\n }\n } catch {\n return undefined\n }\n}\n\n/**\n * Annotate each trace hop with the location of the import that created the\n * edge (file:line:col). Skips steps that already have a location.\n */\nexport async function addTraceImportLocations(\n provider: TransformResultProvider,\n trace: Array<{\n file: string\n specifier?: string\n line?: number\n column?: number\n }>,\n importLocCache: ImportLocCache,\n findImportSpecifierLocationIndex: FindImportSpecifierLocationIndex,\n): Promise<void> {\n for (const step of trace) {\n if (!step.specifier) continue\n if (step.line != null && step.column != null) continue\n const loc = await findImportStatementLocationFromTransformed(\n provider,\n step.file,\n step.specifier,\n importLocCache,\n findImportSpecifierLocationIndex,\n )\n if (!loc) continue\n step.line = loc.line\n step.column = loc.column\n }\n}\n\n// Code snippet extraction (vitest-style context around a location)\n\nexport interface CodeSnippet {\n /** Source lines with line numbers, e.g. `[\" 6 | import { getSecret } from './secret.server'\", ...]` */\n lines: Array<string>\n /** The highlighted line (1-indexed original line number) */\n highlightLine: number\n /** Clickable file:line reference */\n location: string\n}\n\n/**\n * Build a vitest-style code snippet showing lines surrounding a location.\n *\n * Prefers `originalCode` from the sourcemap's sourcesContent; falls back\n * to transformed code when unavailable.\n */\nexport function buildCodeSnippet(\n provider: TransformResultProvider,\n moduleId: string,\n loc: Loc,\n contextLines: number = 2,\n): CodeSnippet | undefined {\n try {\n const importerFile = normalizeFilePath(moduleId)\n const res = provider.getTransformResult(moduleId)\n if (!res) return undefined\n\n const sourceCode = res.originalCode ?? res.code\n const targetLine = loc.line // 1-indexed\n const targetCol = loc.column // 1-indexed\n\n if (targetLine < 1) return undefined\n\n const allLines = sourceCode.split('\\n')\n // Strip trailing \\r from \\r\\n line endings\n for (let i = 0; i < allLines.length; i++) {\n const line = allLines[i]!\n if (line.endsWith('\\r')) allLines[i] = line.slice(0, -1)\n }\n\n const wantStart = Math.max(1, targetLine - contextLines)\n const wantEnd = Math.min(allLines.length, targetLine + contextLines)\n\n if (targetLine > allLines.length) return undefined\n\n const lines = allLines.slice(wantStart - 1, wantEnd)\n const gutterWidth = String(wantEnd).length\n\n const sourceFile = loc.file ?? importerFile\n const snippetLines: Array<string> = []\n for (let i = 0; i < lines.length; i++) {\n const ln = wantStart + i\n const lineContent = lines[i]!\n const lineNumStr = String(ln).padStart(gutterWidth, ' ')\n const marker = ln === targetLine ? '>' : ' '\n snippetLines.push(` ${marker} ${lineNumStr} | ${lineContent}`)\n\n if (ln === targetLine && targetCol > 0) {\n const padding = ' '.repeat(targetCol - 1)\n snippetLines.push(` ${' '.repeat(gutterWidth)} | ${padding}^`)\n }\n }\n\n return {\n lines: snippetLines,\n highlightLine: targetLine,\n location: `${sourceFile}:${targetLine}:${targetCol}`,\n }\n } catch {\n return undefined\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"sourceLocation.js","names":[],"sources":["../../../src/import-protection/sourceLocation.ts"],"sourcesContent":["import { SourceMapConsumer } from 'source-map'\nimport * as path from 'pathe'\n\nimport {\n findOriginalUnsafeUsagePosFromResult,\n findPostCompileUsagePosFromResult,\n getImportSpecifierLocationFromResult,\n} from './analysis'\nimport { getOrCreate, normalizeFilePath } from './utils'\nimport type { ImportAnalysis } from './analysis'\nimport type { Loc } from './trace'\nimport type { ParseAstResult } from '@tanstack/router-utils'\nimport type { RawSourceMap } from 'source-map'\n\n// Source-map type compatible with both Rollup's SourceMap and source-map's\n// RawSourceMap. Structural type avoids version: number vs string mismatch.\n\n/**\n * Minimal source-map shape used throughout the import-protection plugin.\n */\nexport interface SourceMapLike {\n file?: string\n sourceRoot?: string\n version: number | string\n sources: Array<string>\n names: Array<string>\n sourcesContent?: Array<string | null>\n mappings: string\n}\n\n// Transform result provider (replaces ctx.load() which doesn't work in dev)\nexport interface TransformResult {\n code: string\n filename?: string\n map: SourceMapLike | undefined\n originalCode: string | undefined\n originalResult?: TransformResult\n /** Precomputed line index for `code` (index → line/col). */\n lineIndex?: LineIndex\n parsedAst?: ParseAstResult\n analysis?: ImportAnalysis\n}\n\n/**\n * Provides the transformed code and composed sourcemap for a module.\n *\n * Populated from a late-running transform hook. By the time `resolveId`\n * fires for an import, the importer has already been fully transformed.\n */\nexport interface TransformResultProvider {\n getTransformResult: (id: string) => TransformResult | undefined\n}\n\nexport interface ImportSpecifierLocationIndex {\n find: FindImportSpecifierLocationIndex\n}\n\n// Index → line/column conversion\n\nexport type LineIndex = {\n offsets: Array<number>\n}\n\nexport function buildLineIndex(code: string): LineIndex {\n const offsets: Array<number> = [0]\n for (let i = 0; i < code.length; i++) {\n if (code.charCodeAt(i) === 10) {\n offsets.push(i + 1)\n }\n }\n return { offsets }\n}\n\nfunction upperBound(values: Array<number>, x: number): number {\n let lo = 0\n let hi = values.length\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if (values[mid]! <= x) lo = mid + 1\n else hi = mid\n }\n return lo\n}\n\nfunction indexToLineColWithIndex(\n lineIndex: LineIndex,\n idx: number,\n): { line: number; column0: number } {\n const offsets = lineIndex.offsets\n const ub = upperBound(offsets, idx)\n const lineIdx = Math.max(0, ub - 1)\n const line = lineIdx + 1\n\n const lineStart = offsets[lineIdx] ?? 0\n return { line, column0: Math.max(0, idx - lineStart) }\n}\n\nexport function indexToLineColumn(\n lineIndex: LineIndex,\n idx: number,\n): { line: number; column: number } {\n const { line, column0 } = indexToLineColWithIndex(lineIndex, idx)\n return {\n line,\n column: column0 + 1,\n }\n}\n\nexport function normalizeSourceMap(map: SourceMapLike | null | undefined):\n | {\n version: number\n file: string\n sourceRoot?: string\n sources: Array<string>\n names: Array<string>\n sourcesContent?: Array<string>\n mappings: string\n }\n | undefined {\n if (!map) {\n return undefined\n }\n\n return {\n ...map,\n version: Number(map.version),\n file: map.file ?? '',\n names: Array.isArray(map.names) ? map.names : [],\n sourcesContent:\n map.sourcesContent?.map((value) => value ?? '') ?? undefined,\n }\n}\n\n/**\n * Pick the most-likely original source text for `importerFile` from\n * a sourcemap that may contain multiple sources.\n */\nexport function pickOriginalCodeFromSourcesContent(\n map: SourceMapLike | undefined,\n importerFile: string,\n root: string,\n): string | undefined {\n if (!map?.sourcesContent || map.sources.length === 0) {\n return undefined\n }\n\n const file = normalizeFilePath(importerFile)\n const sourceRoot = map.sourceRoot\n const fileSeg = file.split('/').filter(Boolean)\n\n const resolveBase = sourceRoot ? path.resolve(root, sourceRoot) : root\n\n let bestIdx = -1\n let bestScore = -1\n\n for (let i = 0; i < map.sources.length; i++) {\n const content = map.sourcesContent[i]\n if (typeof content !== 'string') continue\n\n const src = map.sources[i] ?? ''\n\n const normalizedSrc = normalizeFilePath(src)\n if (normalizedSrc === file) {\n return content\n }\n\n let resolved: string\n if (!src) {\n resolved = ''\n } else if (path.isAbsolute(src)) {\n resolved = normalizeFilePath(src)\n } else {\n resolved = normalizeFilePath(path.resolve(resolveBase, src))\n }\n if (resolved === file) {\n return content\n }\n\n // Count matching path segments from the end.\n const normalizedSrcSeg = normalizedSrc.split('/').filter(Boolean)\n const resolvedSeg =\n resolved !== normalizedSrc\n ? resolved.split('/').filter(Boolean)\n : normalizedSrcSeg\n const score = Math.max(\n segmentSuffixScore(normalizedSrcSeg, fileSeg),\n segmentSuffixScore(resolvedSeg, fileSeg),\n )\n\n if (score > bestScore) {\n bestScore = score\n bestIdx = i\n }\n }\n\n if (bestIdx !== -1 && bestScore >= 1) {\n return map.sourcesContent[bestIdx] ?? undefined\n }\n\n return map.sourcesContent[0] ?? undefined\n}\n\n/** Count matching path segments from the end of `aSeg` against `bSeg`. */\nfunction segmentSuffixScore(aSeg: Array<string>, bSeg: Array<string>): number {\n let score = 0\n for (\n let i = aSeg.length - 1, j = bSeg.length - 1;\n i >= 0 && j >= 0;\n i--, j--\n ) {\n if (aSeg[i] !== bSeg[j]) break\n score++\n }\n return score\n}\n\nasync function mapGeneratedToOriginal(\n map: SourceMapLike | undefined,\n generated: { line: number; column0: number },\n fallbackFile: string,\n): Promise<Loc> {\n const fallback: Loc = {\n file: fallbackFile,\n line: generated.line,\n column: generated.column0 + 1,\n }\n\n if (!map) {\n return fallback\n }\n\n const consumer = await getSourceMapConsumer(map)\n if (!consumer) return fallback\n\n try {\n const orig = consumer.originalPositionFor({\n line: generated.line,\n column: generated.column0,\n })\n if (orig.line != null && orig.column != null) {\n return {\n file: orig.source ? normalizeFilePath(orig.source) : fallbackFile,\n line: orig.line,\n column: orig.column + 1,\n }\n }\n } catch {\n // Malformed sourcemap\n }\n\n return fallback\n}\n\nconst consumerCache = new WeakMap<object, Promise<SourceMapConsumer | null>>()\n\nfunction toRawSourceMap(map: SourceMapLike): RawSourceMap {\n return {\n ...map,\n file: map.file ?? '',\n version: Number(map.version),\n sourcesContent: map.sourcesContent?.map((s) => s ?? '') ?? [],\n }\n}\n\nasync function getSourceMapConsumer(\n map: SourceMapLike,\n): Promise<SourceMapConsumer | null> {\n const cached = consumerCache.get(map)\n if (cached) return cached\n\n const promise = (async () => {\n try {\n return await new SourceMapConsumer(toRawSourceMap(map))\n } catch {\n return null\n }\n })()\n\n consumerCache.set(map, promise)\n return promise\n}\n\nexport type ImportLocEntry = { file?: string; line: number; column: number }\n\n/**\n * Cache for import statement locations with reverse index for O(1)\n * invalidation by file. Keys: `${importerFile}::${source}`.\n */\nexport class ImportLocCache {\n private cache = new Map<string, ImportLocEntry | null>()\n private reverseIndex = new Map<string, Set<string>>()\n\n has(key: string): boolean {\n return this.cache.has(key)\n }\n\n get(key: string): ImportLocEntry | null | undefined {\n return this.cache.get(key)\n }\n\n set(key: string, value: ImportLocEntry | null): void {\n this.cache.set(key, value)\n const file = key.slice(0, key.indexOf('::'))\n getOrCreate(this.reverseIndex, file, () => new Set()).add(key)\n }\n\n clear(): void {\n this.cache.clear()\n this.reverseIndex.clear()\n }\n\n /** Remove all cache entries where the importer matches `file`. */\n deleteByFile(file: string): void {\n const keys = this.reverseIndex.get(file)\n if (keys) {\n for (const key of keys) {\n this.cache.delete(key)\n }\n this.reverseIndex.delete(file)\n }\n }\n}\n\nexport type FindImportSpecifierLocationIndex = (\n result: TransformResult,\n source: string,\n) => number\n\nexport function getOrCreateOriginalTransformResult(\n result: TransformResult,\n): TransformResult | undefined {\n if (!result.originalCode) {\n return undefined\n }\n\n if (!result.originalResult) {\n result.originalResult = {\n code: result.originalCode,\n filename: result.filename,\n map: undefined,\n originalCode: result.originalCode,\n }\n }\n\n return result.originalResult\n}\n\nexport function createImportSpecifierLocationIndex(): ImportSpecifierLocationIndex {\n return {\n find(result: TransformResult, source: string): number {\n if (!result.code.includes(source)) {\n return -1\n }\n\n return getImportSpecifierLocationFromResult(result, source)\n },\n }\n}\n\n/**\n * Find the location of an import statement in a transformed module\n * by searching the post-transform code and mapping back via sourcemap.\n * Results are cached in `importLocCache`.\n */\nexport async function findImportStatementLocationFromTransformed(\n provider: TransformResultProvider,\n importerId: string,\n source: string,\n importLocCache: ImportLocCache,\n findImportSpecifierLocationIndex: FindImportSpecifierLocationIndex,\n): Promise<Loc | undefined> {\n const importerFile = normalizeFilePath(importerId)\n const cacheKey = `${importerFile}::${source}`\n if (importLocCache.has(cacheKey)) {\n return importLocCache.get(cacheKey) ?? undefined\n }\n\n try {\n const res = provider.getTransformResult(importerId)\n if (!res) {\n importLocCache.set(cacheKey, null)\n return undefined\n }\n\n const { map } = res\n\n const lineIndex =\n res.lineIndex ?? (res.lineIndex = buildLineIndex(res.code))\n\n const idx = findImportSpecifierLocationIndex(res, source)\n if (idx === -1) {\n importLocCache.set(cacheKey, null)\n return undefined\n }\n\n const generated = indexToLineColWithIndex(lineIndex, idx)\n const loc = await mapGeneratedToOriginal(map, generated, importerFile)\n importLocCache.set(cacheKey, loc)\n return loc\n } catch {\n importLocCache.set(cacheKey, null)\n return undefined\n }\n}\n\n/**\n * Find the first post-compile usage location for a denied import specifier.\n * Best-effort: searches transformed code for non-import uses of imported\n * bindings and maps back to original source via sourcemap.\n */\nexport async function findPostCompileUsageLocation(\n provider: TransformResultProvider,\n importerId: string,\n source: string,\n): Promise<Loc | undefined> {\n try {\n const importerFile = normalizeFilePath(importerId)\n const res = provider.getTransformResult(importerId)\n if (!res) return undefined\n const { code, map } = res\n\n if (!res.lineIndex) {\n res.lineIndex = buildLineIndex(code)\n }\n\n const pos = findPostCompileUsagePosFromResult(res, source)\n if (!pos) return undefined\n\n return await mapGeneratedToOriginal(map, pos, importerFile)\n } catch {\n return undefined\n }\n}\n\n/**\n * Best-effort original-source usage lookup for cases where a later transform\n * removes or rewrites the import from emitted code but preserves the original\n * source in `sourcesContent`.\n */\nexport function findOriginalUsageLocation(\n provider: TransformResultProvider,\n importerId: string,\n source: string,\n envType?: 'client' | 'server',\n): Loc | undefined {\n try {\n const importerFile = normalizeFilePath(importerId)\n const res = provider.getTransformResult(importerId)\n if (!res) return undefined\n const originalResult = getOrCreateOriginalTransformResult(res)\n if (!originalResult) return undefined\n\n const pos = envType\n ? findOriginalUnsafeUsagePosFromResult(originalResult, source, envType)\n : findPostCompileUsagePosFromResult(originalResult, source)\n if (!pos) return undefined\n\n return {\n file: importerFile,\n line: pos.line,\n column: pos.column0 + 1,\n }\n } catch {\n return undefined\n }\n}\n\n/**\n * Annotate each trace hop with the location of the import that created the\n * edge (file:line:col). Skips steps that already have a location.\n */\nexport async function addTraceImportLocations(\n provider: TransformResultProvider,\n trace: Array<{\n file: string\n specifier?: string\n line?: number\n column?: number\n }>,\n importLocCache: ImportLocCache,\n findImportSpecifierLocationIndex: FindImportSpecifierLocationIndex,\n): Promise<void> {\n for (const step of trace) {\n if (!step.specifier) continue\n if (step.line != null && step.column != null) continue\n const loc = await findImportStatementLocationFromTransformed(\n provider,\n step.file,\n step.specifier,\n importLocCache,\n findImportSpecifierLocationIndex,\n )\n if (!loc) continue\n step.line = loc.line\n step.column = loc.column\n }\n}\n\n// Code snippet extraction (vitest-style context around a location)\n\nexport interface CodeSnippet {\n /** Source lines with line numbers, e.g. `[\" 6 | import { getSecret } from './secret.server'\", ...]` */\n lines: Array<string>\n /** The highlighted line (1-indexed original line number) */\n highlightLine: number\n /** Clickable file:line reference */\n location: string\n}\n\n/**\n * Build a vitest-style code snippet showing lines surrounding a location.\n *\n * Prefers `originalCode` from the sourcemap's sourcesContent; falls back\n * to transformed code when unavailable.\n */\nexport function buildCodeSnippet(\n provider: TransformResultProvider,\n moduleId: string,\n loc: Loc,\n contextLines: number = 2,\n): CodeSnippet | undefined {\n try {\n const importerFile = normalizeFilePath(moduleId)\n const res = provider.getTransformResult(moduleId)\n if (!res) return undefined\n\n const sourceCode = res.originalCode ?? res.code\n const targetLine = loc.line // 1-indexed\n const targetCol = loc.column // 1-indexed\n\n if (targetLine < 1) return undefined\n\n const allLines = sourceCode.split('\\n')\n // Strip trailing \\r from \\r\\n line endings\n for (let i = 0; i < allLines.length; i++) {\n const line = allLines[i]!\n if (line.endsWith('\\r')) allLines[i] = line.slice(0, -1)\n }\n\n const wantStart = Math.max(1, targetLine - contextLines)\n const wantEnd = Math.min(allLines.length, targetLine + contextLines)\n\n if (targetLine > allLines.length) return undefined\n\n const lines = allLines.slice(wantStart - 1, wantEnd)\n const gutterWidth = String(wantEnd).length\n\n const sourceFile = loc.file ?? importerFile\n const snippetLines: Array<string> = []\n for (let i = 0; i < lines.length; i++) {\n const ln = wantStart + i\n const lineContent = lines[i]!\n const lineNumStr = String(ln).padStart(gutterWidth, ' ')\n const marker = ln === targetLine ? '>' : ' '\n snippetLines.push(` ${marker} ${lineNumStr} | ${lineContent}`)\n\n if (ln === targetLine && targetCol > 0) {\n const padding = ' '.repeat(targetCol - 1)\n snippetLines.push(` ${' '.repeat(gutterWidth)} | ${padding}^`)\n }\n }\n\n return {\n lines: snippetLines,\n highlightLine: targetLine,\n location: `${sourceFile}:${targetLine}:${targetCol}`,\n }\n } catch {\n return undefined\n }\n}\n"],"mappings":"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"}
@@ -197,10 +197,12 @@ async function buildTransformResultProvider(opts) {
197
197
  const map = normalizeSourceMap(sourceAndMap.map);
198
198
  const file = getModuleFile(module);
199
199
  const resource = getModuleResource(module);
200
+ const originalCode = map?.sourcesContent ? pickOriginalCodeFromSourcesContent(map, resource ?? file, opts.root) ?? (resource ? await opts.loadOriginalCode(resource) : void 0) : resource ? await opts.loadOriginalCode(resource) : void 0;
200
201
  const result = {
201
202
  code,
203
+ filename: resource ?? file,
202
204
  map,
203
- originalCode: map?.sourcesContent ? pickOriginalCodeFromSourcesContent(map, resource ?? file, opts.root) ?? (resource ? await opts.loadOriginalCode(resource) : void 0) : resource ? await opts.loadOriginalCode(resource) : void 0,
205
+ originalCode,
204
206
  lineIndex: buildLineIndex(code)
205
207
  };
206
208
  if (!hasTransformResult(cache, file)) addTransformResult(cache, file, result);
@@ -334,7 +336,7 @@ async function getMarkerKindForFile(opts) {
334
336
  cached = (async () => {
335
337
  const code = opts.provider.getTransformResult(opts.file)?.originalCode ?? await opts.loadOriginalCode(opts.file);
336
338
  if (!code) return;
337
- const imports = getImportSources(code);
339
+ const imports = getImportSources(code, opts.file);
338
340
  const hasServerOnly = imports.some((source) => opts.config.markerSpecifiers.serverOnly.has(source));
339
341
  const hasClientOnly = imports.some((source) => opts.config.markerSpecifiers.clientOnly.has(source));
340
342
  if (hasServerOnly && !hasClientOnly) return "server";
@@ -489,14 +491,15 @@ function registerImportProtection(api, opts) {
489
491
  if (!shouldCheckImportProtectionImporter(config, file)) return ctx.code;
490
492
  const matchers = getRulesForEnvironment(config, envName);
491
493
  const relativeFile = getImportProtectionRelativePath(config.root, file);
492
- const importSources = getImportSources(ctx.code);
494
+ const importSources = getImportSources(ctx.code, file);
493
495
  const transformedImportSources = new Set(importSources);
494
496
  const transformInputFileSystem = shared.inputFileSystems[envName];
495
497
  const loadOriginalCodeForTransform = transformInputFileSystem ? (target) => loadOriginalCodeFromInputFileSystem(transformInputFileSystem, target) : () => Promise.resolve(void 0);
496
498
  const originalCode = config.command === "build" ? await loadOriginalCode(fileReadCache, file, loadOriginalCodeForTransform) : void 0;
497
- const buildImportSources = originalCode ? getImportSources(originalCode) : [];
499
+ const buildImportSources = originalCode ? getImportSources(originalCode, file) : [];
498
500
  const buildTransformResult = config.command === "build" ? {
499
501
  code: ctx.code,
502
+ filename: file,
500
503
  map: void 0,
501
504
  originalCode,
502
505
  lineIndex: buildLineIndex(ctx.code)
@@ -514,7 +517,7 @@ function registerImportProtection(api, opts) {
514
517
  if (checkFileDenial(relativeFile, matchers) || envType === "client" && markerKind === "server" || envType === "server" && markerKind === "client") {
515
518
  let exportNames = [];
516
519
  try {
517
- exportNames = getNamedExports(ctx.code);
520
+ exportNames = getNamedExports(ctx.code, file);
518
521
  } catch {
519
522
  exportNames = [];
520
523
  }
@@ -532,7 +535,7 @@ function registerImportProtection(api, opts) {
532
535
  const deniedSpecifierReplacements = /* @__PURE__ */ new Map();
533
536
  const exportsBySource = (() => {
534
537
  try {
535
- return getMockExportNamesBySource(ctx.code);
538
+ return getMockExportNamesBySource(ctx.code, file);
536
539
  } catch {
537
540
  return /* @__PURE__ */ new Map();
538
541
  }