Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions src/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { unlinkSync, existsSync, lstatSync } from 'fs'
import * as promisify from 'util.promisify'
import { sync as rimrafSync } from 'rimraf'
import { createRequire, createRequireFromPath } from 'module'
import { pathToFileURL } from 'url'
import Module = require('module')

const execP = promisify(exec)
Expand All @@ -28,7 +29,7 @@ let { register, create, VERSION }: typeof tsNodeTypes = {} as any

// Pack and install ts-node locally, necessary to test package "exports"
before(async function () {
this.timeout(30000)
this.timeout(5 * 60e3)
rimrafSync(join(TEST_DIR, 'node_modules'))
await execP(`npm install`, { cwd: TEST_DIR })
const packageLockPath = join(TEST_DIR, 'package-lock.json')
Expand Down Expand Up @@ -724,7 +725,7 @@ describe('ts-node', function () {
describe('esm', () => {
this.slow(1000)

const cmd = `node --loader ts-node/esm.mjs`
const cmd = `node --loader ts-node/esm`

if (semver.gte(process.version, '13.0.0')) {
it('should compile and execute as ESM', (done) => {
Expand All @@ -735,6 +736,19 @@ describe('ts-node', function () {
return done()
})
})
it('should use source maps', function (done) {
exec(`${cmd} throw.ts`, { cwd: join(__dirname, '../tests/esm') }, function (err, stdout) {
expect(err).not.to.equal(null)
expect(err!.message).to.contain([
`${pathToFileURL(join(__dirname, '../tests/esm/throw.ts'))}:100`,
' bar () { throw new Error(\'this is a demo\') }',
' ^',
'Error: this is a demo'
].join('\n'))

return done()
})
})
it('supports --experimental-specifier-resolution=node', (done) => {
exec(`${cmd} --experimental-specifier-resolution=node index.ts`, { cwd: join(__dirname, '../tests/esm-node-resolver') }, function (err, stdout) {
expect(err).to.equal(null)
Expand Down
15 changes: 13 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import sourceMapSupport = require('source-map-support')
import * as ynModule from 'yn'
import { BaseError } from 'make-error'
import * as util from 'util'
import { fileURLToPath } from 'url'
import * as _ts from 'typescript'

/**
Expand Down Expand Up @@ -445,8 +446,18 @@ export function create (rawOptions: CreateOptions = {}): Register {
// Install source map support and read from memory cache.
sourceMapSupport.install({
environment: 'node',
retrieveFile (path: string) {
return outputCache.get(normalizeSlashes(path))?.content || ''
retrieveFile (pathOrUrl: string) {
let path = pathOrUrl
// If it's a file URL, convert to local path
// Note: fileURLToPath does not exist on early node v10
// I could not find a way to handle non-URLs except to swallow an error
if (options.experimentalEsmLoader && path.startsWith('file://')) {
try {
path = fileURLToPath(path)
} catch (e) {/* swallow error */}
}
path = normalizeSlashes(path)
return outputCache.get(path)?.content || ''
}
})

Expand Down
103 changes: 103 additions & 0 deletions tests/esm/throw.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// intentional whitespace to prove that sourcemaps are working. Throw should happen on line 100.
// 100 lines is meant to be far more space than the helper functions would take.
class Foo {































































































constructor () { this.bar() }
bar () { throw new Error('this is a demo') }
}
new Foo()
export {}