diff --git a/tegg/core/loader/src/LoaderUtil.ts b/tegg/core/loader/src/LoaderUtil.ts index 1158c2b962..7bd67bf32d 100644 --- a/tegg/core/loader/src/LoaderUtil.ts +++ b/tegg/core/loader/src/LoaderUtil.ts @@ -43,6 +43,10 @@ export class LoaderUtil { return LoaderUtil.supportExtensions().includes('.ts') ? '.ts' : '.js'; } + static isWindowsPlatform(): boolean { + return process.platform === 'win32'; + } + static filePattern(): string[] { const extensions = LoaderUtil.supportExtensions(); const extensionPattern = extensions @@ -79,7 +83,7 @@ export class LoaderUtil { throw createLoadError(originalFilePath, e); } if (exports == null) { - if (process.platform === 'win32') { + if (LoaderUtil.isWindowsPlatform()) { // convert to file:// url // avoid windows path issue: Only URLs with a scheme in: file, data, and node are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'd:' filePath = pathToFileURL(filePath).toString(); @@ -87,7 +91,7 @@ export class LoaderUtil { try { exports = await import(filePath); } catch (e: unknown) { - throw createLoadError(filePath, e); + throw createLoadError(originalFilePath, e); } } const clazzList: EggProtoImplClass[] = []; diff --git a/tegg/core/loader/test/Loader.test.ts b/tegg/core/loader/test/Loader.test.ts index a2dfb0ed8d..3a33580b6d 100644 --- a/tegg/core/loader/test/Loader.test.ts +++ b/tegg/core/loader/test/Loader.test.ts @@ -4,7 +4,7 @@ import path from 'node:path'; import { PrototypeUtil, SingletonProto } from '@eggjs/core-decorator'; import { EggLoadUnitType } from '@eggjs/metadata'; import type {} from '@eggjs/typings/global'; -import { afterEach, describe, it } from 'vitest'; +import { afterEach, describe, it, vi } from 'vitest'; import { LoaderFactory, LoaderUtil } from '../src/index.ts'; @@ -92,6 +92,26 @@ describe('core/loader/test/Loader.test.ts', () => { }, ); }); + + it('should keep the caller path when wrapping dynamic import errors on win32', async () => { + const missingFile = path.join(__dirname, './fixtures/modules/module-for-loader/MissingService.ts'); + globalThis.__EGG_BUNDLE_MODULE_LOADER__ = () => undefined; + + const isWindowsPlatform = vi.spyOn(LoaderUtil, 'isWindowsPlatform').mockReturnValue(true); + try { + await assert.rejects( + async () => { + await LoaderUtil.loadFile(missingFile); + }, + (err: Error) => { + assert(err.message.startsWith(`[tegg/loader] load ${missingFile} failed:`)); + return true; + }, + ); + } finally { + isWindowsPlatform.mockRestore(); + } + }); }); describe('file has tsc error', () => {