-
-
Notifications
You must be signed in to change notification settings - Fork 6.4k
/
repl.ts
110 lines (100 loc) · 3.12 KB
/
repl.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
declare const jestGlobalConfig: Config.GlobalConfig;
declare const jestProjectConfig: Config.ProjectConfig;
import * as path from 'path';
import * as repl from 'repl';
import {runInThisContext} from 'vm';
import type {SyncTransformer} from '@jest/transform';
import type {Config} from '@jest/types';
import {interopRequireDefault} from 'jest-util';
// TODO: support async as well
let transformer: SyncTransformer;
let transformerConfig: unknown;
const evalCommand: repl.REPLEval = (
cmd: string,
_context: unknown,
_filename: string,
callback: (e: Error | null, result?: unknown) => void,
) => {
let result;
try {
if (transformer) {
const transformResult = transformer.process(
cmd,
jestGlobalConfig.replname || 'jest.js',
{
cacheFS: new Map<string, string>(),
config: jestProjectConfig,
configString: JSON.stringify(jestProjectConfig),
instrument: false,
supportsDynamicImport: false,
supportsExportNamespaceFrom: false,
supportsStaticESM: false,
supportsTopLevelAwait: false,
transformerConfig,
},
);
cmd =
typeof transformResult === 'string'
? transformResult
: transformResult.code;
}
result = runInThisContext(cmd);
} catch (e: any) {
return callback(isRecoverableError(e) ? new repl.Recoverable(e) : e);
}
return callback(null, result);
};
const isRecoverableError = (error: Error) => {
if (error && error.name === 'SyntaxError') {
return [
'Unterminated template',
'Missing } in template expression',
'Unexpected end of input',
'missing ) after argument list',
'Unexpected token',
].some(exception => error.message.includes(exception));
}
return false;
};
if (jestProjectConfig.transform) {
let transformerPath = null;
for (let i = 0; i < jestProjectConfig.transform.length; i++) {
if (new RegExp(jestProjectConfig.transform[i][0]).test('foobar.js')) {
transformerPath = jestProjectConfig.transform[i][1];
transformerConfig = jestProjectConfig.transform[i][2];
break;
}
}
if (transformerPath) {
const transformerOrFactory = interopRequireDefault(
require(transformerPath),
).default;
if (typeof transformerOrFactory.createTransformer === 'function') {
transformer = transformerOrFactory.createTransformer(transformerConfig);
} else {
transformer = transformerOrFactory;
}
if (typeof transformer.process !== 'function') {
throw new TypeError(
'Jest: a transformer must export a `process` function.',
);
}
}
}
const replInstance: repl.REPLServer = repl.start({
eval: evalCommand,
prompt: '\u203A ',
useGlobal: true,
});
replInstance.context.require = (moduleName: string) => {
if (/(\/|\\|\.)/.test(moduleName)) {
moduleName = path.resolve(process.cwd(), moduleName);
}
return require(moduleName);
};