Skip to content

Commit df4de4d

Browse files
authored
feat: Add --use-spawn-wrap=true option (#1169)
Completely bypass spawn-wrap unless overridden with this new option.
1 parent 408c1cb commit df4de4d

File tree

11 files changed

+128
-73
lines changed

11 files changed

+128
-73
lines changed

bin/nyc.js

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@
33

44
const configUtil = require('../lib/config-util')
55
const foreground = require('foreground-child')
6+
const resolveFrom = require('resolve-from')
67
const NYC = require('../index.js')
78

8-
const sw = require('spawn-wrap')
9-
const wrapper = require.resolve('./wrap.js')
10-
119
// parse configuration and command-line arguments;
1210
// we keep these values in a few different forms,
1311
// used in the various execution contexts of nyc:
@@ -44,10 +42,7 @@ async function main () {
4442
await nyc.addAllFiles()
4543
}
4644

47-
var env = {
48-
// Support running nyc as a user without HOME (e.g. linux 'nobody'),
49-
// https://github.com/istanbuljs/nyc/issues/951
50-
SPAWN_WRAP_SHIM_ROOT: process.env.SPAWN_WRAP_SHIM_ROOT || process.env.XDG_CACHE_HOME || require('os').homedir(),
45+
const env = {
5146
NYC_CONFIG: JSON.stringify(argv),
5247
NYC_CWD: process.cwd()
5348
}
@@ -58,7 +53,29 @@ async function main () {
5853
env.BABEL_DISABLE_CACHE = process.env.BABEL_DISABLE_CACHE = '1'
5954
}
6055

61-
sw([wrapper], env)
56+
if (!argv.useSpawnWrap) {
57+
const { preloadAppend, propagateEnv } = require('node-preload')
58+
59+
nyc.require.forEach(requireModule => {
60+
const mod = resolveFrom.silent(nyc.cwd, requireModule) || requireModule
61+
preloadAppend(mod)
62+
require(mod)
63+
})
64+
preloadAppend(require.resolve('../lib/wrap.js'))
65+
Object.assign(propagateEnv, env)
66+
}
67+
68+
if (argv.all) nyc.addAllFiles()
69+
70+
if (argv.useSpawnWrap) {
71+
const wrapper = require.resolve('./wrap.js')
72+
// Support running nyc as a user without HOME (e.g. linux 'nobody'),
73+
// https://github.com/istanbuljs/nyc/issues/951
74+
env.SPAWN_WRAP_SHIM_ROOT = process.env.SPAWN_WRAP_SHIM_ROOT || process.env.XDG_CACHE_HOME || require('os').homedir()
75+
const sw = require('spawn-wrap')
76+
77+
sw([wrapper], env)
78+
}
6279

6380
// Both running the test script invocation and the check-coverage run may
6481
// set process.exitCode. Keep track so that both children are run, but

bin/wrap.js

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,2 @@
1-
var sw = require('spawn-wrap')
2-
var NYC = require('../index.js')
3-
4-
var config = {}
5-
if (process.env.NYC_CONFIG) config = JSON.parse(process.env.NYC_CONFIG)
6-
config.isChildProcess = true
7-
8-
config._processInfo = {
9-
pid: process.pid,
10-
ppid: process.ppid,
11-
parent: process.env.NYC_PROCESS_ID || null
12-
}
13-
if (process.env.NYC_PROCESSINFO_EXTERNAL_ID) {
14-
config._processInfo.externalId = process.env.NYC_PROCESSINFO_EXTERNAL_ID
15-
delete process.env.NYC_PROCESSINFO_EXTERNAL_ID
16-
}
17-
18-
if (process.env.NYC_CONFIG_OVERRIDE) {
19-
const override = JSON.parse(process.env.NYC_CONFIG_OVERRIDE)
20-
config = {
21-
...config,
22-
...override
23-
}
24-
process.env.NYC_CONFIG = JSON.stringify(config)
25-
}
26-
27-
;(new NYC(config)).wrap()
28-
29-
sw.runMain()
1+
require('../lib/wrap')
2+
require('spawn-wrap').runMain()

index.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ class NYC {
129129
}
130130

131131
_loadAdditionalModules () {
132+
if (!this.config.useSpawnWrap) {
133+
return
134+
}
135+
132136
this.require.forEach(requireModule => {
133137
// Attempt to require the module relative to the directory being instrumented.
134138
// Then try other locations, e.g. the nyc node_modules folder.
@@ -347,6 +351,12 @@ class NYC {
347351

348352
wrap (bin) {
349353
process.env.NYC_PROCESS_ID = this.processInfo.uuid
354+
// This is a bug with the spawn-wrap method where
355+
// we cannot force propagation of NYC_PROCESS_ID.
356+
if (!this.config.useSpawnWrap) {
357+
const { propagateEnv } = require('node-preload')
358+
propagateEnv.NYC_PROCESS_ID = this.processInfo.uuid
359+
}
350360
this._addRequireHooks()
351361
this._wrapExit()
352362
this._loadAdditionalModules()

lib/config-util.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,12 @@ async function processConfig (cwd) {
201201
type: 'boolean',
202202
global: false
203203
})
204+
.option('use-spawn-wrap', {
205+
describe: 'use spawn-wrap instead of setting process.env.NODE_OPTIONS',
206+
default: false,
207+
type: 'boolean',
208+
global: false
209+
})
204210
.option('clean', {
205211
describe: 'should the .nyc_output folder be cleaned before executing tests',
206212
default: true,

lib/wrap.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const NYC = require('../index.js')
2+
3+
let config = {}
4+
if (process.env.NYC_CONFIG) {
5+
config = JSON.parse(process.env.NYC_CONFIG)
6+
}
7+
config.isChildProcess = true
8+
9+
config._processInfo = {
10+
pid: process.pid,
11+
ppid: process.ppid,
12+
parent: process.env.NYC_PROCESS_ID || null
13+
}
14+
15+
if (process.env.NYC_PROCESSINFO_EXTERNAL_ID) {
16+
config._processInfo.externalId = process.env.NYC_PROCESSINFO_EXTERNAL_ID
17+
delete process.env.NYC_PROCESSINFO_EXTERNAL_ID
18+
}
19+
20+
if (process.env.NYC_CONFIG_OVERRIDE) {
21+
const override = JSON.parse(process.env.NYC_CONFIG_OVERRIDE)
22+
config = {
23+
...config,
24+
...override
25+
}
26+
process.env.NYC_CONFIG = JSON.stringify(config)
27+
}
28+
29+
;(new NYC(config)).wrap()

package-lock.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
"make-dir": "^3.0.0",
8888
"merge-source-map": "^1.1.0",
8989
"p-map": "^3.0.0",
90+
"node-preload": "^0.1.2",
9091
"resolve-from": "^5.0.0",
9192
"rimraf": "^3.0.0",
9293
"signal-exit": "^3.0.2",

tap-snapshots/test-nyc-integration.js-TAP.test.js

Lines changed: 33 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ All files | 0 | 0 | 0 | 0 |
113113
external-instrumenter.js | 0 | 0 | 0 | 0 | 1
114114
gc.js | 0 | 100 | 100 | 0 | 2,3
115115
half-covered-failing.js | 0 | 0 | 100 | 0 | 1,3,5,6,7,8
116-
selfspawn-fibonacci.js | 0 | 0 | 0 | 0 | ...19,21,24,25,26,27,28
116+
selfspawn-fibonacci.js | 0 | 0 | 0 | 0 | ...21,23,26,27,28,29,30
117117
skip-full.js | 0 | 100 | 100 | 0 | 1,2
118118
test.js | 0 | 0 | 0 | 0 |
119119
cli/fakebin | 0 | 100 | 100 | 0 |
@@ -144,8 +144,8 @@ exports[`test/nyc-integration.js TAP --ignore-class-method skips methods that ma
144144
---------------------------------|---------|----------|---------|---------|-------------------------
145145
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
146146
---------------------------------|---------|----------|---------|---------|-------------------------
147-
All files | 1.45 | 0 | 5 | 1.89 |
148-
cli | 2.08 | 0 | 5.56 | 3.13 |
147+
All files | 1.44 | 0 | 5 | 1.87 |
148+
cli | 2.06 | 0 | 5.56 | 3.08 |
149149
args.js | 0 | 100 | 100 | 0 | 1
150150
by-arg2.js | 0 | 0 | 100 | 0 | 1,2,3,4,5,7
151151
classes.js | 66.67 | 100 | 50 | 66.67 | 6
@@ -158,7 +158,7 @@ All files | 1.45 | 0 | 5 | 1.89 |
158158
gc.js | 0 | 100 | 100 | 0 | 2,3
159159
half-covered-failing.js | 0 | 0 | 100 | 0 | 1,3,5,6,7,8
160160
half-covered.js | 0 | 0 | 100 | 0 | 1,3,5,6,7,8
161-
selfspawn-fibonacci.js | 0 | 0 | 0 | 0 | ...19,21,24,25,26,27,28
161+
selfspawn-fibonacci.js | 0 | 0 | 0 | 0 | ...21,23,26,27,28,29,30
162162
skip-full.js | 0 | 100 | 100 | 0 | 1,2
163163
cli/fakebin | 0 | 100 | 100 | 0 |
164164
npm-template.js | 0 | 100 | 100 | 0 | 2,3,4,7,9
@@ -202,8 +202,8 @@ exports[`test/nyc-integration.js TAP --show-process-tree displays a tree of spaw
202202
------------------------|---------|----------|---------|---------|-------------------
203203
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
204204
------------------------|---------|----------|---------|---------|-------------------
205-
All files | 90.91 | 70 | 100 | 100 |
206-
selfspawn-fibonacci.js | 90.91 | 70 | 100 | 100 | 4,25,27
205+
All files | 91.3 | 70 | 100 | 100 |
206+
selfspawn-fibonacci.js | 91.3 | 70 | 100 | 100 | 6,27,29
207207
------------------------|---------|----------|---------|---------|-------------------
208208
nyc
209209
│ 100 % Lines
@@ -214,19 +214,41 @@ nyc
214214
│ ├─┬ node ./selfspawn-fibonacci.js 3
215215
│ │ │ 100 % Lines
216216
│ │ ├── node ./selfspawn-fibonacci.js 2
217-
│ │ │ 31.58 % Lines
217+
│ │ │ 35 % Lines
218218
│ │ └── node ./selfspawn-fibonacci.js 1
219-
│ │ 26.32 % Lines
219+
│ │ 30 % Lines
220220
│ └── node ./selfspawn-fibonacci.js 2
221-
31.58 % Lines
221+
35 % Lines
222222
└─┬ node ./selfspawn-fibonacci.js 3
223223
│ 100 % Lines
224224
├── node ./selfspawn-fibonacci.js 2
225-
31.58 % Lines
225+
35 % Lines
226226
└── node ./selfspawn-fibonacci.js 1
227-
26.32 % Lines
227+
30 % Lines
228228
229229
230+
`
231+
232+
exports[`test/nyc-integration.js TAP --use-spawn-wrap=false is functional > stdout 1`] = `
233+
3
234+
------------------------|---------|----------|---------|---------|-------------------
235+
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
236+
------------------------|---------|----------|---------|---------|-------------------
237+
All files | 91.3 | 70 | 100 | 100 |
238+
selfspawn-fibonacci.js | 91.3 | 70 | 100 | 100 | 6,27,29
239+
------------------------|---------|----------|---------|---------|-------------------
240+
241+
`
242+
243+
exports[`test/nyc-integration.js TAP --use-spawn-wrap=true is functional > stdout 1`] = `
244+
3
245+
------------------------|---------|----------|---------|---------|-------------------
246+
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
247+
------------------------|---------|----------|---------|---------|-------------------
248+
All files | 91.3 | 70 | 100 | 100 |
249+
selfspawn-fibonacci.js | 91.3 | 70 | 100 | 100 | 6,27,29
250+
------------------------|---------|----------|---------|---------|-------------------
251+
230252
`
231253

232254
exports[`test/nyc-integration.js TAP allows .nycrc configuration to be overridden with command line args > stdout 1`] = `
@@ -853,30 +875,6 @@ exports[`test/nyc-integration.js TAP passes configuration via environment variab
853875
]
854876
`
855877

856-
exports[`test/nyc-integration.js TAP produce-source-map enabled > stdout 1`] = `
857-
Error: Blarrh
858-
at blah (./stack-trace.js:3:1)
859-
----------------|---------|----------|---------|---------|-------------------
860-
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
861-
----------------|---------|----------|---------|---------|-------------------
862-
All files | 100 | 100 | 100 | 100 |
863-
stack-trace.js | 100 | 100 | 100 | 100 |
864-
----------------|---------|----------|---------|---------|-------------------
865-
866-
`
867-
868-
exports[`test/nyc-integration.js TAP produce-source-map not enabled > stdout 1`] = `
869-
Error: Blarrh
870-
at blah (./stack-trace.js:1:1037)
871-
----------------|---------|----------|---------|---------|-------------------
872-
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
873-
----------------|---------|----------|---------|---------|-------------------
874-
All files | 100 | 100 | 100 | 100 |
875-
stack-trace.js | 100 | 100 | 100 | 100 |
876-
----------------|---------|----------|---------|---------|-------------------
877-
878-
`
879-
880878
exports[`test/nyc-integration.js TAP recursive run does not throw > stdout 1`] = `
881879
882880
`

test/add-all-files.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,11 @@ t.test('transpiles .js files added via addAllFiles', async t => {
6060
'utf-8'
6161
)
6262

63-
const nyc = new NYC(await parseArgv(fixtures, ['--require', transpileHook]))
63+
const nyc = new NYC(await parseArgv(fixtures, [
64+
'--use-spawn-wrap=true',
65+
'--require',
66+
transpileHook
67+
]))
6468
await nyc.reset()
6569
await nyc.addAllFiles()
6670

@@ -83,6 +87,7 @@ t.test('does not attempt to transpile files when they are excluded', async t =>
8387
)
8488

8589
const nyc = new NYC(await parseArgv(fixtures, [
90+
'--use-spawn-wrap=true',
8691
`--require=${transpileHook}`,
8792
'--extension=.do-not-transpile',
8893
'--include=needs-transpile.do-not-transpile'
@@ -103,6 +108,7 @@ t.test('transpiles non-.js files added via addAllFiles', async t => {
103108
)
104109

105110
const nyc = new NYC(await parseArgv(fixtures, [
111+
'--use-spawn-wrap=true',
106112
`--require=${transpileHook}`,
107113
'--extension=.whatever'
108114
]))

test/fixtures/cli/selfspawn-fibonacci.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
'use strict';
22
var cp = require('child_process');
33

4+
process.env = {};
5+
46
var index = +process.argv[2] || 0
57
if (index <= 1) {
68
console.log(0)

test/nyc-integration.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,14 @@ t.test('--show-process-tree displays a tree of spawned processes', t => testSucc
186186
args: ['--show-process-tree', process.execPath, 'selfspawn-fibonacci.js', '5']
187187
}))
188188

189+
t.test('--use-spawn-wrap=true is functional', t => testSuccess(t, {
190+
args: ['--use-spawn-wrap=true', process.execPath, 'selfspawn-fibonacci.js', '5']
191+
}))
192+
193+
t.test('--use-spawn-wrap=false is functional', t => testSuccess(t, {
194+
args: ['--use-spawn-wrap=false', process.execPath, 'selfspawn-fibonacci.js', '5']
195+
}))
196+
189197
t.test('can run "npm test" which directly invokes a test file', t => testSuccess(t, {
190198
args: ['npm', 'test'],
191199
cwd: path.resolve(fixturesCLI, 'run-npm-test')

0 commit comments

Comments
 (0)