@@ -5,7 +5,7 @@ import debugModule from 'debug'
55const debug = debugModule ( 'codeceptjs:container' )
66import { MetaStep } from './step.js'
77import { methodsOfObject , fileExists , isFunction , isAsyncFunction , installedLocally , deepMerge } from './utils.js'
8- import { transpileTypeScript , cleanupTempFiles } from './utils/typescript.js'
8+ import { transpileTypeScript , cleanupTempFiles , fixErrorStack } from './utils/typescript.js'
99import Translation from './translation.js'
1010import MochaFactory from './mocha/factory.js'
1111import recorder from './recorder.js'
@@ -34,6 +34,7 @@ let container = {
3434 /** @type {Result | null } */
3535 result : null ,
3636 sharedKeys : new Set ( ) , // Track keys shared via share() function
37+ tsFileMapping : null , // TypeScript file mapping for error stack fixing
3738}
3839
3940/**
@@ -88,7 +89,7 @@ class Container {
8889 container . support . I = mod
8990 }
9091 } catch ( e ) {
91- throw new Error ( `Could not include object I: ${ e . message } ` )
92+ throw e
9293 }
9394 } else {
9495 // Create default actor - this sets up the callback in asyncHelperPromise
@@ -176,6 +177,15 @@ class Container {
176177 return container . translation
177178 }
178179
180+ /**
181+ * Get TypeScript file mapping for error stack fixing
182+ *
183+ * @api
184+ */
185+ static tsFileMapping ( ) {
186+ return container . tsFileMapping
187+ }
188+
179189 /**
180190 * Get Mocha instance
181191 *
@@ -401,18 +411,27 @@ async function requireHelperFromModule(helperName, config, HelperClass) {
401411 // Handle TypeScript files
402412 let importPath = moduleName
403413 let tempJsFile = null
414+ let fileMapping = null
404415 const ext = path . extname ( moduleName )
405416
406417 if ( ext === '.ts' ) {
407418 try {
408419 // Use the TypeScript transpilation utility
409420 const typescript = await import ( 'typescript' )
410- const { tempFile, allTempFiles } = await transpileTypeScript ( importPath , typescript )
421+ const { tempFile, allTempFiles, fileMapping : mapping } = await transpileTypeScript ( importPath , typescript )
411422
412423 debug ( `Transpiled TypeScript helper: ${ importPath } -> ${ tempFile } ` )
413424
414425 importPath = tempFile
415426 tempJsFile = allTempFiles
427+ fileMapping = mapping
428+ // Store file mapping in container for runtime error fixing (merge with existing)
429+ if ( ! container . tsFileMapping ) {
430+ container . tsFileMapping = new Map ( )
431+ }
432+ for ( const [ key , value ] of mapping . entries ( ) ) {
433+ container . tsFileMapping . set ( key , value )
434+ }
416435 } catch ( tsError ) {
417436 throw new Error ( `Failed to load TypeScript helper ${ importPath } : ${ tsError . message } . Make sure 'typescript' package is installed.` )
418437 }
@@ -433,6 +452,11 @@ async function requireHelperFromModule(helperName, config, HelperClass) {
433452 cleanupTempFiles ( filesToClean )
434453 }
435454 } catch ( err ) {
455+ // Fix error stack to point to original .ts files
456+ if ( fileMapping ) {
457+ fixErrorStack ( err , fileMapping )
458+ }
459+
436460 // Clean up temp files before rethrowing
437461 if ( tempJsFile ) {
438462 const filesToClean = Array . isArray ( tempJsFile ) ? tempJsFile : [ tempJsFile ]
@@ -731,6 +755,7 @@ async function loadSupportObject(modulePath, supportObjectName) {
731755 // Use dynamic import for both ESM and CJS modules
732756 let importPath = modulePath
733757 let tempJsFile = null
758+ let fileMapping = null
734759
735760 if ( typeof importPath === 'string' ) {
736761 const ext = path . extname ( importPath )
@@ -740,14 +765,22 @@ async function loadSupportObject(modulePath, supportObjectName) {
740765 try {
741766 // Use the TypeScript transpilation utility
742767 const typescript = await import ( 'typescript' )
743- const { tempFile, allTempFiles } = await transpileTypeScript ( importPath , typescript )
768+ const { tempFile, allTempFiles, fileMapping : mapping } = await transpileTypeScript ( importPath , typescript )
744769
745770 debug ( `Transpiled TypeScript file: ${ importPath } -> ${ tempFile } ` )
746771
747772 // Attach cleanup handler
748773 importPath = tempFile
749774 // Store temp files list in a way that cleanup can access them
750775 tempJsFile = allTempFiles
776+ fileMapping = mapping
777+ // Store file mapping in container for runtime error fixing (merge with existing)
778+ if ( ! container . tsFileMapping ) {
779+ container . tsFileMapping = new Map ( )
780+ }
781+ for ( const [ key , value ] of mapping . entries ( ) ) {
782+ container . tsFileMapping . set ( key , value )
783+ }
751784 } catch ( tsError ) {
752785 throw new Error ( `Failed to load TypeScript file ${ importPath } : ${ tsError . message } . Make sure 'typescript' package is installed.` )
753786 }
@@ -761,6 +794,11 @@ async function loadSupportObject(modulePath, supportObjectName) {
761794 try {
762795 obj = await import ( importPath )
763796 } catch ( importError ) {
797+ // Fix error stack to point to original .ts files
798+ if ( fileMapping ) {
799+ fixErrorStack ( importError , fileMapping )
800+ }
801+
764802 // Clean up temp files if created before rethrowing
765803 if ( tempJsFile ) {
766804 const filesToClean = Array . isArray ( tempJsFile ) ? tempJsFile : [ tempJsFile ]
@@ -809,7 +847,9 @@ async function loadSupportObject(modulePath, supportObjectName) {
809847
810848 throw new Error ( `Support object "${ supportObjectName } " should be an object, class, or function, but got ${ typeof actualObj } ` )
811849 } catch ( err ) {
812- throw new Error ( `Could not include object ${ supportObjectName } from module '${ modulePath } '\n${ err . message } \n${ err . stack } ` )
850+ const newErr = new Error ( `Could not include object ${ supportObjectName } from module '${ modulePath } ': ${ err . message } ` )
851+ newErr . stack = err . stack
852+ throw newErr
813853 }
814854}
815855
0 commit comments