Skip to content

Commit aca788a

Browse files
committed
feat: enhance stack trace for import
1 parent ac25df2 commit aca788a

File tree

6 files changed

+32
-22
lines changed

6 files changed

+32
-22
lines changed

packages/core/src/registry.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ class Registry<out C extends Context = Context> {
189189
return this.plugin({ inject, apply: callback, name: callback.name })
190190
}
191191

192-
plugin(plugin: Plugin<C>, config?: any, getOuterStack: () => Iterable<string> = buildOuterStack()) {
192+
plugin(plugin: Plugin<C>, config?: any, getOuterStack = buildOuterStack()) {
193193
// check if it's a valid plugin
194194
const callback = this.resolve(plugin)
195195
if (!callback) throw new Error('invalid plugin, expect function or object with an "apply" method, received ' + typeof plugin)

packages/core/src/scope.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export class EffectScope<out C extends Context = Context> {
6262
config: any,
6363
public inject: Dict<Inject.Meta>,
6464
public runtime: Plugin.Runtime | null,
65-
private getOuterStack: () => Iterable<string>,
65+
private getOuterStack: () => string[],
6666
) {
6767
if (parent.scope) {
6868
this.uid = parent.registry.counter
@@ -193,6 +193,7 @@ export class EffectScope<out C extends Context = Context> {
193193
private async _reload() {
194194
try {
195195
await composeError(async (info) => {
196+
info.offset += 1
196197
let result: any
197198
if (isConstructor(this.runtime!.callback)) {
198199
// eslint-disable-next-line new-cap
@@ -217,7 +218,7 @@ export class EffectScope<out C extends Context = Context> {
217218
this.disposables.push(dispose)
218219
}
219220
}
220-
}, 2, this.getOuterStack)
221+
}, this.getOuterStack)
221222
} catch (reason) {
222223
// the registry impl guarantees that the error is non-null
223224
this.context.emit(this.ctx, 'internal/error', reason)
@@ -232,7 +233,7 @@ export class EffectScope<out C extends Context = Context> {
232233
private async _unload() {
233234
await Promise.all(this.disposables.clear().map(async (dispose) => {
234235
try {
235-
await composeError(dispose, 1, this.getOuterStack)
236+
await composeError(dispose, this.getOuterStack)
236237
} catch (reason) {
237238
this.context.emit(this.ctx, 'internal/error', reason)
238239
}

packages/core/src/utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,10 +229,10 @@ interface StackInfo {
229229
offset: number
230230
}
231231

232-
export async function composeError<T>(callback: (info: StackInfo) => Promise<T>, offset: number, getOuterStack: () => Iterable<string>) {
232+
export async function composeError<T>(callback: (info: StackInfo) => Promise<T>, getOuterStack = buildOuterStack()) {
233233
// force async stack trace
234234
await Promise.resolve()
235-
const info: StackInfo = { offset }
235+
const info: StackInfo = { offset: 1 }
236236

237237
try {
238238
return await callback(info)

packages/hmr/src/index.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,11 @@ class HMR extends Service {
134134
})
135135
}
136136

137+
// hide stack trace from HMR
138+
getOuterStack = (): string[] => [
139+
// ' at HMR.partialReload (<anonymous>)',
140+
]
141+
137142
async getLinked(filename: string) {
138143
// The second parameter `type` should always be `javascript`.
139144
const job = this.internal.loadCache.get(pathToFileURL(filename).toString())
@@ -271,26 +276,25 @@ class HMR extends Service {
271276
const attempts: Dict = {}
272277
try {
273278
for (const [, { filename }] of reloads) {
274-
attempts[filename] = this.ctx.loader.unwrapExports(await import(filename))
279+
attempts[filename] = this.ctx.loader.unwrapExports(await this.ctx.loader.import(filename, this.getOuterStack))
275280
}
276281
} catch (e) {
277282
handleError(this.ctx, e)
278283
return rollback()
279284
}
280285

281-
const reload = (plugin: any, runtime?: Plugin.Runtime) => {
286+
const reload = (plugin: any, runtime: Plugin.Runtime) => {
282287
if (!runtime) return
283288
for (const oldFiber of runtime.scopes) {
284-
const scope = oldFiber.parent.registry.plugin(plugin, oldFiber.config, () => [
285-
' at HMR.partialReload (<anonymous>)',
286-
])
289+
const scope = oldFiber.parent.registry.plugin(plugin, oldFiber.config, this.getOuterStack)
287290
scope.entry = oldFiber.entry
288291
if (scope.entry) scope.entry.scope = scope
289292
}
290293
}
291294

292295
try {
293296
for (const [plugin, { filename, runtime }] of reloads) {
297+
if (!runtime) continue
294298
const path = this.relative(fileURLToPath(filename))
295299

296300
try {
@@ -313,6 +317,7 @@ class HMR extends Service {
313317
// rollback cache and plugin states
314318
rollback()
315319
for (const [plugin, { filename, runtime }] of reloads) {
320+
if (!runtime) continue
316321
try {
317322
this.ctx.registry.delete(attempts[filename])
318323
reload(plugin, runtime)

packages/loader/src/config/entry.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { composeError, Context, EffectScope } from '@cordisjs/core'
1+
import { Context, EffectScope } from '@cordisjs/core'
22
import { isNullable } from 'cosmokit'
33
import { Loader } from '../loader.ts'
44
import { EntryGroup } from './group.ts'
@@ -157,9 +157,7 @@ export class Entry<C extends Context = Context> {
157157
private async _init() {
158158
let exports: any
159159
try {
160-
exports = await composeError(async () => {
161-
return this.parent.tree.import(this.options.name)
162-
}, 2, this.getOuterStack)
160+
exports = await this.parent.tree.import(this.options.name, this.getOuterStack, true)
163161
} catch (error) {
164162
this.context.emit(this.ctx, 'internal/error', error)
165163
return

packages/loader/src/config/tree.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Context } from '@cordisjs/core'
1+
import { composeError, Context } from '@cordisjs/core'
22
import { Dict } from 'cosmokit'
33
import { Entry, EntryOptions } from './entry.ts'
44
import { EntryGroup } from './group.ts'
@@ -95,12 +95,18 @@ export abstract class EntryTree<C extends Context = Context> {
9595
return entry.update(options)
9696
}
9797

98-
async import(name: string) {
99-
if (this.ctx.loader.internal) {
100-
return await this.ctx.loader.internal.import(name, this.url, {})
101-
} else {
102-
return await import(name)
103-
}
98+
import(name: string, getOuterStack?: () => string[], useInternal = false) {
99+
return composeError(async (info) => {
100+
// ModuleJob.run
101+
// onImport.tracePromise.__proto__
102+
// internal.import
103+
info.offset += 3
104+
if (useInternal && this.ctx.loader.internal) {
105+
return await this.ctx.loader.internal.import(name, this.url, {})
106+
} else {
107+
return await import(name)
108+
}
109+
}, getOuterStack)
104110
}
105111

106112
abstract write(): void

0 commit comments

Comments
 (0)