|
1 | 1 | /* eslint-disable @sentry-internal/sdk/no-optional-chaining */
|
| 2 | +import type { ExportNamedDeclaration } from '@babel/types'; |
2 | 3 | import * as fs from 'fs';
|
| 4 | +import { parseModule } from 'magicast'; |
3 | 5 | import * as path from 'path';
|
4 | 6 | import type { Plugin } from 'vite';
|
5 | 7 |
|
@@ -89,24 +91,50 @@ export function makeAutoInstrumentationPlugin(options: AutoInstrumentPluginOptio
|
89 | 91 | */
|
90 | 92 | export async function canWrapLoad(id: string, debug: boolean): Promise<boolean> {
|
91 | 93 | const code = (await fs.promises.readFile(id, 'utf8')).toString();
|
| 94 | + const mod = parseModule(code); |
92 | 95 |
|
93 |
| - const codeWithoutComments = code.replace(/(\/\/.*| ?\/\*[^]*?\*\/)(,?)$/gm, ''); |
94 |
| - |
95 |
| - const hasSentryContent = codeWithoutComments.includes('@sentry/sveltekit'); |
96 |
| - if (hasSentryContent) { |
| 96 | + const program = mod.$ast.type === 'Program' && mod.$ast; |
| 97 | + if (!program) { |
97 | 98 | // eslint-disable-next-line no-console
|
98 |
| - debug && console.log(`Skipping wrapping ${id} because it already contains Sentry code`); |
| 99 | + debug && console.log(`Skipping wrapping ${id} because it doesn't contain valid JavaScript or TypeScript`); |
| 100 | + return false; |
99 | 101 | }
|
100 | 102 |
|
101 |
| - const hasLoadDeclaration = /((const|let|var|function)\s+load\s*(=|\(|:))|as\s+load\s*(,|})/gm.test( |
102 |
| - codeWithoutComments, |
103 |
| - ); |
| 103 | + const hasLoadDeclaration = program.body |
| 104 | + .filter((statement): statement is ExportNamedDeclaration => statement.type === 'ExportNamedDeclaration') |
| 105 | + .find(exportDecl => { |
| 106 | + // find `export const load = ...` |
| 107 | + if (exportDecl.declaration && exportDecl.declaration.type === 'VariableDeclaration') { |
| 108 | + const variableDeclarations = exportDecl.declaration.declarations; |
| 109 | + return variableDeclarations.find(decl => decl.id.type === 'Identifier' && decl.id.name === 'load'); |
| 110 | + } |
| 111 | + |
| 112 | + // find `export function load = ...` |
| 113 | + if (exportDecl.declaration && exportDecl.declaration.type === 'FunctionDeclaration') { |
| 114 | + const functionId = exportDecl.declaration.id; |
| 115 | + return functionId?.name === 'load'; |
| 116 | + } |
| 117 | + |
| 118 | + // find `export { load, somethingElse as load, somethingElse as "load" }` |
| 119 | + if (exportDecl.specifiers) { |
| 120 | + return exportDecl.specifiers.find(specifier => { |
| 121 | + return ( |
| 122 | + (specifier.exported.type === 'Identifier' && specifier.exported.name === 'load') || |
| 123 | + (specifier.exported.type === 'StringLiteral' && specifier.exported.value === 'load') |
| 124 | + ); |
| 125 | + }); |
| 126 | + } |
| 127 | + |
| 128 | + return false; |
| 129 | + }); |
| 130 | + |
104 | 131 | if (!hasLoadDeclaration) {
|
105 | 132 | // eslint-disable-next-line no-console
|
106 | 133 | debug && console.log(`Skipping wrapping ${id} because it doesn't declare a \`load\` function`);
|
| 134 | + return false; |
107 | 135 | }
|
108 | 136 |
|
109 |
| - return !hasSentryContent && hasLoadDeclaration; |
| 137 | + return true; |
110 | 138 | }
|
111 | 139 |
|
112 | 140 | /**
|
|
0 commit comments