11import * as puppeteer from 'puppeteer' ;
2- import { relative , join , isAbsolute , dirname , posix , sep , resolve } from 'path' ;
2+ import { relative , join , isAbsolute , dirname } from 'path' ;
33import type { BoundQueries } from './pptr-testing-library' ;
44import { getQueriesForElement } from './pptr-testing-library' ;
55import { connectToBrowser } from './connect-to-browser' ;
@@ -11,16 +11,13 @@ import _ansiRegex from 'ansi-regex';
1111import { fileURLToPath } from 'url' ;
1212import type { PleasantestUser } from './user' ;
1313import { pleasantestUser } from './user' ;
14- import {
15- assertElementHandle ,
16- printStackLine ,
17- removeFuncFromStackTrace ,
18- } from './utils' ;
14+ import { assertElementHandle , removeFuncFromStackTrace } from './utils' ;
1915import type { ModuleServerOpts } from './module-server' ;
2016import { createModuleServer } from './module-server' ;
2117import { cleanupClientRuntimeServer } from './module-server/client-runtime-server' ;
2218import { Console } from 'console' ;
2319import { createBuildStatusTracker } from './module-server/build-status-tracker' ;
20+ import { sourceMapErrorFromBrowser } from './source-map-error-from-browser' ;
2421
2522export { JSHandle , ElementHandle } from 'puppeteer' ;
2623koloristOpts . enabled = true ;
@@ -320,7 +317,7 @@ const createTab = async ({
320317 // This uses the testPath as the url so that if there are relative imports
321318 // in the inline code, the relative imports are resolved relative to the test file
322319 const url = `http://localhost:${ port } /${ testPath } ?inline-code=${ encodedCode } &build-id=${ buildStatus . buildId } ` ;
323- const res = ( await safeEvaluate (
320+ const res = await safeEvaluate (
324321 runJS ,
325322 new Function (
326323 '...args' ,
@@ -334,91 +331,13 @@ const createTab = async ({
334331 : e)` ,
335332 ) as ( ) => any ,
336333 ...( Array . isArray ( args ) ? ( args as any ) : [ ] ) ,
337- ) ) as undefined | { message : string ; stack : string } ;
334+ ) ;
338335
339336 const errorsFromBuild = buildStatus . complete ( ) ;
340337 // It only throws the first one but that is probably OK
341338 if ( errorsFromBuild ) throw errorsFromBuild [ 0 ] ;
342339
343- if ( res === undefined ) return ;
344- if ( typeof res !== 'object' ) throw res ;
345- const { message, stack } = res ;
346- const parsedStack = parseStackTrace ( stack ) ;
347- const modifiedStack = parsedStack . map ( async ( stackItem ) => {
348- if ( stackItem . raw . startsWith ( stack . slice ( 0 , stack . indexOf ( '\n' ) ) ) )
349- return null ;
350- if ( ! stackItem . fileName ) return stackItem . raw ;
351- const fileName = stackItem . fileName ;
352- const line = stackItem . line ;
353- const column = stackItem . column ;
354- if ( ! fileName . startsWith ( `http://localhost:${ port } ` ) )
355- return stackItem . raw ;
356- const url = new URL ( fileName ) ;
357- const osPath = url . pathname . slice ( 1 ) . split ( posix . sep ) . join ( sep ) ;
358- // Absolute file path
359- const file = resolve ( process . cwd ( ) , osPath ) ;
360- // Rollup-style Unix-normalized path "id":
361- const id = file . split ( sep ) . join ( posix . sep ) ;
362- const transformResult = requestCache . get ( id ) ;
363- const map = typeof transformResult === 'object' && transformResult . map ;
364- if ( ! map ) {
365- let p = url . pathname ;
366- const npmPrefix = '/@npm/' ;
367- if ( p . startsWith ( npmPrefix ) )
368- p = join ( process . cwd ( ) , 'node_modules' , p . slice ( npmPrefix . length ) ) ;
369- return printStackLine ( p , line , column , stackItem . name ) ;
370- }
371-
372- const { SourceMapConsumer } = await import ( 'source-map' ) ;
373- const consumer = await new SourceMapConsumer ( map as any ) ;
374- const sourceLocation = consumer . originalPositionFor ( {
375- line,
376- column : column - 1 , // Source-map uses zero-based column numbers
377- } ) ;
378- consumer . destroy ( ) ;
379- return printStackLine (
380- join ( process . cwd ( ) , url . pathname ) ,
381- sourceLocation . line ?? line ,
382- sourceLocation . column === null
383- ? column
384- : // Convert back from zero-based column to 1-based
385- sourceLocation . column + 1 ,
386- stackItem . name ,
387- ) ;
388- } ) ;
389- const errorName = stack . slice ( 0 , stack . indexOf ( ':' ) ) || 'Error' ;
390- const specializedErrors = {
391- EvalError,
392- RangeError,
393- ReferenceError,
394- SyntaxError,
395- TypeError,
396- URIError,
397- } as any ;
398- const ErrorConstructor : ErrorConstructor =
399- specializedErrors [ errorName ] || Error ;
400- const error = new ErrorConstructor ( message ) ;
401-
402- const finalStack = ( await Promise . all ( modifiedStack ) )
403- . filter ( Boolean )
404- . join ( '\n' ) ;
405-
406- // If the browser error did not provide a stack, use the stack trace from node
407- if ( finalStack ) {
408- error . stack = `${ errorName } : ${ message } \n${ finalStack } ` ;
409- } else {
410- removeFuncFromStackTrace ( error , runJS ) ;
411- if ( error . stack )
412- error . stack = error . stack
413- . split ( '\n' )
414- . filter (
415- // This was appearing in stack traces and it messed up the Jest output
416- ( line ) => ! ( / r u n M i c r o t a s k s / . test ( line ) && / < a n o n y m o u s > / . test ( line ) ) ,
417- )
418- . join ( '\n' ) ;
419- }
420-
421- throw error ;
340+ await sourceMapErrorFromBrowser ( res , requestCache , port , runJS ) ;
422341 } ;
423342
424343 const injectHTML : PleasantestUtils [ 'injectHTML' ] = async ( html ) => {
@@ -459,10 +378,21 @@ const createTab = async ({
459378 const fullPath = jsPath . startsWith ( '.' )
460379 ? join ( dirname ( testPath ) , jsPath )
461380 : jsPath ;
462- await safeEvaluate (
381+ const buildStatus = createBuildStatusTracker ( ) ;
382+ const url = `http://localhost:${ port } /${ fullPath } ?build-id=${ buildStatus . buildId } ` ;
383+ const res = await safeEvaluate (
463384 loadJS ,
464- `import(${ JSON . stringify ( `http://localhost:${ port } /${ fullPath } ` ) } )` ,
385+ `import(${ JSON . stringify ( url ) } )
386+ .catch(e => e instanceof Error
387+ ? { message: e.message, stack: e.stack }
388+ : e)` ,
465389 ) ;
390+
391+ const errorsFromBuild = buildStatus . complete ( ) ;
392+ // It only throws the first one but that is probably OK
393+ if ( errorsFromBuild ) throw errorsFromBuild [ 0 ] ;
394+
395+ await sourceMapErrorFromBrowser ( res , requestCache , port , loadJS ) ;
466396 } ;
467397
468398 const utils : PleasantestUtils = {
0 commit comments