(name: string, stack?: string[])
| 131 | * Analyzes stack trace of error created inside the function call. |
| 132 | */ |
| 133 | export function lookupPathFromDecorator(name: string, stack?: string[]): string { |
| 134 | // use some dark magic to get source path to caller |
| 135 | stack = stack || new Error().stack!.split('\n'); |
| 136 | // In some situations (e.g. swc 1.3.4+), the presence of a source map can obscure the call to |
| 137 | // __decorate(), replacing it with the constructor name. To support these cases we look for |
| 138 | // Reflect.decorate() as well. Also when babel is used, we need to check |
| 139 | // the `_applyDecoratedDescriptor` method instead. TypeScript 5+ emits `__esDecorate` |
| 140 | // (inlined into the user file) for TC39 stage-3 native decorators. |
| 141 | let line = stack.findIndex(line => |
| 142 | /__decorate|__esDecorate|Reflect\.decorate|_applyDecoratedDescriptor|applyClassDecs/.exec(line), |
| 143 | ); |
| 144 | |
| 145 | // Bun can skip decorator helper frames. Native ES decorators expose the entity |
| 146 | // path right after `bun:wrap`, while reflect-metadata stacks reach it via Reflect.js. |
| 147 | if (line === -1) { |
| 148 | const bunWrapLine = stack.findLastIndex(stackLine => stackLine.includes('bun:wrap')); |
| 149 | |
| 150 | if (bunWrapLine !== -1 && bunWrapLine + 1 < stack.length) { |
| 151 | line = bunWrapLine + 1; |
| 152 | } else { |
| 153 | const reflectLine = stack.findLastIndex(stackLine => |
| 154 | stackLine.replace(/\\/g, '/').includes('node_modules/reflect-metadata/Reflect.js'), |
| 155 | ); |
| 156 | |
| 157 | if (reflectLine === -1 || reflectLine + 2 >= stack.length || !stack[reflectLine + 1].includes('bun:wrap')) { |
| 158 | return name; |
| 159 | } |
| 160 | |
| 161 | line = reflectLine + 2; |
| 162 | } |
| 163 | } |
| 164 | |
| 165 | if (stack[line].includes('Reflect.decorate')) { |
| 166 | line++; |
| 167 | } |
| 168 | |
| 169 | // Skip decorator runtime helpers (tslib, @oxc-project/runtime, etc.) |
| 170 | // The @oxc-project/runtime check covers both node_modules installs and Rolldown-bundled |
| 171 | // virtual modules (e.g. \0@oxc-project+runtime@0.120.0/helpers/decorate.js). |
| 172 | while (line < stack.length && /node_modules\/tslib\/|@oxc-project[/+]runtime/.test(stack[line].replace(/\\/g, '/'))) { |
| 173 | line++; |
| 174 | } |
| 175 | |
| 176 | try { |
| 177 | const re = /\(.+\)/i.exec(stack[line]) ? /\((.*?)(?::\d+){1,2}\)/ : /at\s*(.*?)(?::\d+){1,2}$/; |
| 178 | return stack[line].match(re)![1]; |
| 179 | } catch { |
| 180 | return name; |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | /** Retrieves or creates the metadata object for a decorated entity class. */ |
| 185 | export function getMetadataFromDecorator<T = any>( |
no test coverage detected