@@ -9,18 +9,22 @@ import {
9
9
tsxEsmApiCjsPath ,
10
10
type NodeApis ,
11
11
} from '../utils/tsx.js' ;
12
- import { createPackageJson , createTsconfig } from '../fixtures.js' ;
12
+ import { createPackageJson , createTsconfig , expectErrors } from '../fixtures.js' ;
13
13
14
14
const tsFiles = {
15
15
'file.ts' : `
16
16
import { foo } from './foo'
17
- export const message = foo as string
17
+ export const message = \`\${foo} \${(typeof __filename === 'undefined' ? import.meta.url : __filename).split(/[\\\\/]/).pop()}\` as string
18
+ export { async } from './foo'
18
19
` ,
19
20
'foo.ts' : `
21
+ import { setTimeout } from 'node:timers/promises'
20
22
import { bar } from './bar.js'
21
23
export const foo = \`foo \${bar}\` as string
24
+ export const async = setTimeout(10).then(() => require('./async')).catch((error) => error);
22
25
` ,
23
26
'bar.ts' : 'export type A = 1; export { bar } from "pkg"' ,
27
+ 'async.ts' : 'export default "async"' ,
24
28
'node_modules/pkg' : {
25
29
'package.json' : createPackageJson ( {
26
30
name : 'pkg' ,
@@ -29,6 +33,7 @@ const tsFiles = {
29
33
} ) ,
30
34
'index.js' : 'import "node:process"; export const bar = "bar";' ,
31
35
} ,
36
+ ...expectErrors ,
32
37
} ;
33
38
34
39
export default testSuite ( ( { describe } , node : NodeApis ) => {
@@ -83,7 +88,7 @@ export default testSuite(({ describe }, node: NodeApis) => {
83
88
nodeOptions : [ ] ,
84
89
} ) ;
85
90
86
- expect ( stdout ) . toBe ( 'Fails as expected\nfoo bar\nUnregistered' ) ;
91
+ expect ( stdout ) . toBe ( 'Fails as expected\nfoo bar file.ts \nUnregistered' ) ;
87
92
} ) ;
88
93
89
94
describe ( 'tsx.require()' , ( { test } ) => {
@@ -120,16 +125,16 @@ export default testSuite(({ describe }, node: NodeApis) => {
120
125
nodeOptions : [ ] ,
121
126
} ) ;
122
127
123
- expect ( stdout ) . toBe ( ' Fails as expected\nfoo bar\nfile.ts\nUnpolluted global require' ) ;
128
+ expect ( stdout ) . toMatch ( / F a i l s a s e x p e c t e d \n f o o b a r f i l e . t s \n f i l e .t s \? n a m e s p a c e = \d + \ nU n p o l l u t e d g l o b a l r e q u i r e / ) ;
124
129
} ) ;
125
130
126
131
test ( 'catchable' , async ( ) => {
127
132
await using fixture = await createFixture ( {
128
133
'require.cjs' : `
129
134
const tsx = require(${ JSON . stringify ( tsxCjsApiPath ) } );
130
- try { tsx.require('./file ', __filename); } catch {}
135
+ try { tsx.require('./syntax-error ', __filename); } catch {}
131
136
` ,
132
- 'file .ts' : 'if' ,
137
+ 'syntax-error .ts' : 'if' ,
133
138
} ) ;
134
139
135
140
const { all } = await execaNode ( fixture . getPath ( 'require.cjs' ) , [ ] , {
@@ -139,6 +144,77 @@ export default testSuite(({ describe }, node: NodeApis) => {
139
144
} ) ;
140
145
expect ( all ) . toBe ( '' ) ;
141
146
} ) ;
147
+
148
+ test ( 'chainable' , async ( ) => {
149
+ await using fixture = await createFixture ( {
150
+ 'require.cjs' : `
151
+ const path = require('node:path');
152
+ const tsx = require(${ JSON . stringify ( tsxCjsApiPath ) } );
153
+
154
+ const unregister = tsx.register();
155
+ console.log(require('./file').message);
156
+ delete require.cache[require.resolve('./file')];
157
+
158
+ const loaded = tsx.require('./file', __filename);
159
+ console.log(loaded.message);
160
+
161
+ // Remove from cache
162
+ const loadedPath = tsx.require.resolve('./file', __filename);
163
+ delete require.cache[loadedPath];
164
+
165
+ console.log(require('./file').message);
166
+ delete require.cache[require.resolve('./file')];
167
+
168
+ unregister();
169
+
170
+ try {
171
+ require('./file');
172
+ } catch {
173
+ console.log('Unregistered');
174
+ }
175
+ ` ,
176
+ ...tsFiles ,
177
+ } ) ;
178
+
179
+ const { stdout } = await execaNode ( fixture . getPath ( 'require.cjs' ) , [ ] , {
180
+ nodePath : node . path ,
181
+ nodeOptions : [ ] ,
182
+ } ) ;
183
+
184
+ expect ( stdout ) . toBe ( 'foo bar file.ts\nfoo bar file.ts\nfoo bar file.ts\nUnregistered' ) ;
185
+ } ) ;
186
+
187
+ test ( 'namespace' , async ( ) => {
188
+ await using fixture = await createFixture ( {
189
+ 'require.cjs' : `
190
+ const { expectErrors } = require('expect-errors');
191
+ const path = require('node:path');
192
+ const tsx = require(${ JSON . stringify ( tsxCjsApiPath ) } );
193
+
194
+ const api = tsx.register({ namespace: 'abcd' });
195
+
196
+ expectErrors(
197
+ // Loading explicit/resolved file path should be ignored by loader (extensions)
198
+ [() => require('./file.ts'), 'SyntaxError'],
199
+
200
+ // resolver should preserve full file path when ignoring
201
+ [() => require('./file.ts?asdf'), "Cannot find module './file.ts?asdf'"]
202
+ );
203
+
204
+ const { message, async } = api.require('./file', __filename);
205
+ console.log(message);
206
+ async.then(m => console.log(m.default));
207
+ ` ,
208
+ ...tsFiles ,
209
+ } ) ;
210
+
211
+ const { stdout } = await execaNode ( fixture . getPath ( 'require.cjs' ) , [ ] , {
212
+ nodePath : node . path ,
213
+ nodeOptions : [ ] ,
214
+ } ) ;
215
+
216
+ expect ( stdout ) . toBe ( 'foo bar file.ts\nasync' ) ;
217
+ } ) ;
142
218
} ) ;
143
219
} ) ;
144
220
@@ -185,7 +261,7 @@ export default testSuite(({ describe }, node: NodeApis) => {
185
261
nodeOptions : [ ] ,
186
262
} ) ;
187
263
188
- expect ( stdout ) . toBe ( 'Fails as expected\nfoo bar' ) ;
264
+ expect ( stdout ) . toBe ( 'Fails as expected\nfoo bar file.ts?nocache ' ) ;
189
265
} ) ;
190
266
191
267
describe ( 'register / unregister' , ( { test, describe } ) => {
@@ -199,7 +275,7 @@ export default testSuite(({ describe }, node: NodeApis) => {
199
275
} catch {
200
276
console.log('Fails as expected 1');
201
277
}
202
-
278
+
203
279
{
204
280
const unregister = register();
205
281
@@ -231,7 +307,7 @@ export default testSuite(({ describe }, node: NodeApis) => {
231
307
nodePath : node . path ,
232
308
nodeOptions : [ ] ,
233
309
} ) ;
234
- expect ( stdout ) . toBe ( 'Fails as expected 1\nfoo bar\nFails as expected 2\nfoo bar' ) ;
310
+ expect ( stdout ) . toBe ( 'Fails as expected 1\nfoo bar file.ts?2 \nFails as expected 2\nfoo bar file.ts?4 ' ) ;
235
311
} ) ;
236
312
237
313
test ( 'onImport' , async ( ) => {
@@ -245,7 +321,7 @@ export default testSuite(({ describe }, node: NodeApis) => {
245
321
console.log(file.split('/').pop());
246
322
},
247
323
});
248
-
324
+
249
325
await import('./file');
250
326
` ,
251
327
...tsFiles ,
@@ -255,7 +331,7 @@ export default testSuite(({ describe }, node: NodeApis) => {
255
331
nodePath : node . path ,
256
332
nodeOptions : [ ] ,
257
333
} ) ;
258
- expect ( stdout ) . toBe ( 'file.ts\nfoo.ts\nbar.ts\nindex.js\nnode:process' ) ;
334
+ expect ( stdout ) . toBe ( 'file.ts\nfoo.ts\npromises\ nbar.ts\nindex.js\nnode:process' ) ;
259
335
} ) ;
260
336
261
337
test ( 'namespace & onImport' , async ( ) => {
@@ -423,17 +499,17 @@ export default testSuite(({ describe }, node: NodeApis) => {
423
499
'package.json' : createPackageJson ( { type : 'module' } ) ,
424
500
'import.mjs' : `
425
501
import { tsImport } from ${ JSON . stringify ( tsxEsmApiPath ) } ;
426
-
502
+
427
503
await import('./file.ts').catch((error) => {
428
504
console.log('Fails as expected 1');
429
505
});
430
-
506
+
431
507
const { message } = await tsImport('./file.ts', import.meta.url);
432
508
console.log(message);
433
-
509
+
434
510
const { message: message2 } = await tsImport('./file.ts?with-query', import.meta.url);
435
511
console.log(message2);
436
-
512
+
437
513
// Global not polluted
438
514
await import('./file.ts?nocache').catch((error) => {
439
515
console.log('Fails as expected 2');
@@ -446,26 +522,26 @@ export default testSuite(({ describe }, node: NodeApis) => {
446
522
nodePath : node . path ,
447
523
nodeOptions : [ ] ,
448
524
} ) ;
449
- expect ( stdout ) . toBe ( ' Fails as expected 1\nfoo bar\ nfoo bar\ nFails as expected 2' ) ;
525
+ expect ( stdout ) . toMatch ( / F a i l s a s e x p e c t e d 1 \n f o o b a r f i l e \. t s \? t s x - n a m e s p a c e = \d + \ nf o o b a r f i l e \. t s \? w i t h - q u e r y = & t s x - n a m e s p a c e = \d + \ nF a i l s a s e x p e c t e d 2 / ) ;
450
526
} ) ;
451
527
452
528
test ( 'commonjs' , async ( ) => {
453
529
await using fixture = await createFixture ( {
454
530
'package.json' : createPackageJson ( { type : 'module' } ) ,
455
531
'import.cjs' : `
456
532
const { tsImport } = require(${ JSON . stringify ( tsxEsmApiCjsPath ) } );
457
-
533
+
458
534
(async () => {
459
535
await import('./file.ts').catch((error) => {
460
536
console.log('Fails as expected 1');
461
537
});
462
-
538
+
463
539
const { message } = await tsImport('./file.ts', __filename);
464
540
console.log(message);
465
-
541
+
466
542
const { message: message2 } = await tsImport('./file.ts?with-query', __filename);
467
543
console.log(message2);
468
-
544
+
469
545
// Global not polluted
470
546
await import('./file.ts?nocache').catch((error) => {
471
547
console.log('Fails as expected 2');
@@ -479,7 +555,7 @@ export default testSuite(({ describe }, node: NodeApis) => {
479
555
nodePath : node . path ,
480
556
nodeOptions : [ ] ,
481
557
} ) ;
482
- expect ( stdout ) . toBe ( ' Fails as expected 1\nfoo bar\ nfoo bar\ nFails as expected 2' ) ;
558
+ expect ( stdout ) . toMatch ( / F a i l s a s e x p e c t e d 1 \n f o o b a r f i l e \. t s \? t s x - n a m e s p a c e = \d + \ nf o o b a r f i l e \. t s \? w i t h - q u e r y = & t s x - n a m e s p a c e = \d + \ nF a i l s a s e x p e c t e d 2 / ) ;
483
559
} ) ;
484
560
485
561
test ( 'mts from commonjs' , async ( ) => {
0 commit comments