Skip to content

Commit 490ed8a

Browse files
authored
Fix #1072 (#1085)
* Fix #1072 * add tests
1 parent 8dfb75c commit 490ed8a

File tree

3 files changed

+109
-31
lines changed

3 files changed

+109
-31
lines changed

dist-raw/node-esm-resolve-implementation.js

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -50,37 +50,7 @@ const {
5050
Stats,
5151
} = require('fs');
5252
// const { getOptionValue } = require('internal/options');
53-
const { getOptionValue } = (() => {
54-
let options;
55-
function parseOptions() {
56-
if (!options) {
57-
options = {
58-
'--preserve-symlinks': false,
59-
'--preserve-symlinks-main': false,
60-
'--input-type': undefined,
61-
'--experimental-specifier-resolution': 'explicit',
62-
...parseExecArgv()
63-
}
64-
}
65-
};
66-
function parseExecArgv () {
67-
return require('arg')({
68-
'--preserve-symlinks': Boolean,
69-
'--preserve-symlinks-main': Boolean,
70-
'--input-type': String,
71-
'--experimental-specifier-resolution': String
72-
}, {
73-
argv: process.execArgv,
74-
permissive: true
75-
});
76-
}
77-
return {
78-
getOptionValue: (opt) => {
79-
parseOptions();
80-
return options[opt];
81-
}
82-
};
83-
})();
53+
const { getOptionValue } = require('./node-options');
8454
const { sep } = require('path');
8555

8656
const preserveSymlinks = getOptionValue('--preserve-symlinks');

dist-raw/node-options.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Replacement for node's internal 'internal/options' module
2+
3+
exports.getOptionValue = getOptionValue;
4+
function getOptionValue(opt) {
5+
parseOptions();
6+
return options[opt];
7+
}
8+
9+
let options;
10+
function parseOptions() {
11+
if (!options) {
12+
options = {
13+
'--preserve-symlinks': false,
14+
'--preserve-symlinks-main': false,
15+
'--input-type': undefined,
16+
'--experimental-specifier-resolution': 'explicit',
17+
...parseArgv(getNodeOptionsEnvArgv()),
18+
...parseArgv(process.execArgv)
19+
}
20+
}
21+
}
22+
23+
function parseArgv(argv) {
24+
return require('arg')({
25+
'--preserve-symlinks': Boolean,
26+
'--preserve-symlinks-main': Boolean,
27+
'--input-type': String,
28+
'--experimental-specifier-resolution': String
29+
}, {
30+
argv,
31+
permissive: true
32+
});
33+
}
34+
35+
function getNodeOptionsEnvArgv() {
36+
const errors = [];
37+
const envArgv = ParseNodeOptionsEnvVar(process.env.NODE_OPTIONS || '', errors);
38+
if (errors.length !== 0) {
39+
// TODO: handle errors somehow
40+
}
41+
return envArgv;
42+
}
43+
44+
// Direct JS port of C implementation: https://github.com/nodejs/node/blob/67ba825037b4082d5d16f922fb9ce54516b4a869/src/node_options.cc#L1024-L1063
45+
function ParseNodeOptionsEnvVar(node_options, errors) {
46+
const env_argv = [];
47+
48+
let is_in_string = false;
49+
let will_start_new_arg = true;
50+
for (let index = 0; index < node_options.length; ++index) {
51+
let c = node_options[index];
52+
53+
// Backslashes escape the following character
54+
if (c === '\\' && is_in_string) {
55+
if (index + 1 === node_options.length) {
56+
errors.push("invalid value for NODE_OPTIONS " +
57+
"(invalid escape)\n");
58+
return env_argv;
59+
} else {
60+
c = node_options[++index];
61+
}
62+
} else if (c === ' ' && !is_in_string) {
63+
will_start_new_arg = true;
64+
continue;
65+
} else if (c === '"') {
66+
is_in_string = !is_in_string;
67+
continue;
68+
}
69+
70+
if (will_start_new_arg) {
71+
env_argv.push(c);
72+
will_start_new_arg = false;
73+
} else {
74+
env_argv[env_argv.length - 1] += c;
75+
}
76+
}
77+
78+
if (is_in_string) {
79+
errors.push("invalid value for NODE_OPTIONS " +
80+
"(unterminated string)\n");
81+
}
82+
return env_argv;
83+
}

src/index.spec.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,8 +767,33 @@ describe('ts-node', function () {
767767

768768
return done()
769769
})
770+
})
771+
772+
describe('supports experimental-specifier-resolution=node', () => {
773+
it('via --experimental-specifier-resolution', (done) => {
774+
exec(`${cmd} --experimental-specifier-resolution=node index.ts`, { cwd: join(__dirname, '../tests/esm-node-resolver') }, function (err, stdout) {
775+
expect(err).to.equal(null)
776+
expect(stdout).to.equal('foo bar baz biff\n')
777+
778+
return done()
779+
})
780+
})
781+
it('via NODE_OPTIONS', (done) => {
782+
exec(`${cmd} index.ts`, {
783+
cwd: join(__dirname, '../tests/esm-node-resolver'),
784+
env: {
785+
...process.env,
786+
NODE_OPTIONS: '--experimental-specifier-resolution=node'
787+
}
788+
}, function (err, stdout) {
789+
expect(err).to.equal(null)
790+
expect(stdout).to.equal('foo bar baz biff\n')
770791

792+
return done()
793+
})
794+
})
771795
})
796+
772797
it('throws ERR_REQUIRE_ESM when attempting to require() an ESM script while ESM loader is enabled', function (done) {
773798
exec(`${cmd} ./index.js`, { cwd: join(__dirname, '../tests/esm-err-require-esm') }, function (err, stdout, stderr) {
774799
expect(err).to.not.equal(null)

0 commit comments

Comments
 (0)