|
1 | 1 | import * as common from '../common/index.mjs'; |
2 | 2 | import tmpdir from '../common/tmpdir.js'; |
3 | 3 | import assert from 'node:assert'; |
| 4 | +import os from 'node:os'; |
4 | 5 | import path from 'node:path'; |
5 | 6 | import { execPath } from 'node:process'; |
6 | 7 | import { describe, it } from 'node:test'; |
@@ -993,4 +994,112 @@ process.on('message', (message) => { |
993 | 994 | await done(); |
994 | 995 | } |
995 | 996 | }); |
| 997 | + |
| 998 | + it('should strip all watch flags from NODE_OPTIONS in child process', async () => { |
| 999 | + const file = createTmpFile('console.log(process.env.NODE_OPTIONS);'); |
| 1000 | + const nodeOptions = [ |
| 1001 | + '--watch', |
| 1002 | + '--watch=true', |
| 1003 | + '--watch-path=./src', |
| 1004 | + '--watch-path', './test', |
| 1005 | + '--watch-preserve-output', |
| 1006 | + '--watch-preserve-output=true', |
| 1007 | + '--watch-kill-signal=SIGKILL', |
| 1008 | + '--watch-kill-signal', 'SIGINT', |
| 1009 | + '--max-old-space-size=4096', |
| 1010 | + '--no-warnings', |
| 1011 | + ].join(' '); |
| 1012 | + const { done, restart } = runInBackground({ |
| 1013 | + args: ['--watch', file], |
| 1014 | + options: { |
| 1015 | + env: { ...process.env, NODE_OPTIONS: nodeOptions }, |
| 1016 | + }, |
| 1017 | + }); |
| 1018 | + |
| 1019 | + try { |
| 1020 | + const { stdout, stderr } = await restart(); |
| 1021 | + |
| 1022 | + assert.strictEqual(stderr, ''); |
| 1023 | + const nodeOptionsLine = stdout.find((line) => line.includes('--max-old-space-size')); |
| 1024 | + assert.ok(nodeOptionsLine); |
| 1025 | + assert.strictEqual(nodeOptionsLine, '--max-old-space-size=4096 --no-warnings'); |
| 1026 | + } finally { |
| 1027 | + await done(); |
| 1028 | + } |
| 1029 | + }); |
| 1030 | + |
| 1031 | + it('should not strip --watch when it appears inside a quoted NODE_OPTIONS value', { |
| 1032 | + // Honoring --require from NODE_OPTIONS is required for this test. |
| 1033 | + skip: !!process.config.variables.node_without_node_options, |
| 1034 | + }, async () => { |
| 1035 | + // Use /tmp to avoid CI directories with special characters (e.g. ") |
| 1036 | + // that would break NODE_OPTIONS parsing. |
| 1037 | + const watchDir = path.join(os.tmpdir(), 'test for --watch parsing'); |
| 1038 | + mkdirSync(watchDir, { recursive: true }); |
| 1039 | + const reqFile = path.join(watchDir, 'req.cjs'); |
| 1040 | + writeFileSync(reqFile, 'globalThis.requiredOk = true;'); |
| 1041 | + |
| 1042 | + const file = createTmpFile('console.log("required:" + !!globalThis.requiredOk);'); |
| 1043 | + const nodeOptions = `--watch --require "${reqFile}"`; |
| 1044 | + const { done, restart } = runInBackground({ |
| 1045 | + args: ['--watch', file], |
| 1046 | + options: { |
| 1047 | + env: { ...process.env, NODE_OPTIONS: nodeOptions }, |
| 1048 | + }, |
| 1049 | + }); |
| 1050 | + |
| 1051 | + try { |
| 1052 | + const { stdout, stderr } = await restart(); |
| 1053 | + |
| 1054 | + assert.strictEqual(stderr, ''); |
| 1055 | + assert.ok(stdout.some((line) => line.includes('required:true'))); |
| 1056 | + } finally { |
| 1057 | + await done(); |
| 1058 | + } |
| 1059 | + }); |
| 1060 | + |
| 1061 | + it('should handle NODE_OPTIONS containing only watch flags', async () => { |
| 1062 | + const file = createTmpFile('console.log(JSON.stringify(process.env.NODE_OPTIONS));'); |
| 1063 | + const { done, restart } = runInBackground({ |
| 1064 | + args: ['--watch', file], |
| 1065 | + options: { |
| 1066 | + env: { ...process.env, NODE_OPTIONS: '--watch' }, |
| 1067 | + }, |
| 1068 | + }); |
| 1069 | + |
| 1070 | + try { |
| 1071 | + const { stdout, stderr } = await restart(); |
| 1072 | + |
| 1073 | + assert.strictEqual(stderr, ''); |
| 1074 | + assert.ok(stdout.some((line) => line.includes('""'))); |
| 1075 | + } finally { |
| 1076 | + await done(); |
| 1077 | + } |
| 1078 | + }); |
| 1079 | + |
| 1080 | + it('should strip multiple --watch-path entries from NODE_OPTIONS', async () => { |
| 1081 | + const file = createTmpFile('console.log(process.env.NODE_OPTIONS);'); |
| 1082 | + // Use /tmp to avoid CI directories with special characters (e.g. ") |
| 1083 | + // that would break NODE_OPTIONS parsing. |
| 1084 | + const dirA = path.join(os.tmpdir(), 'node-watch-path-a'); |
| 1085 | + const dirB = path.join(os.tmpdir(), 'node-watch-path-b'); |
| 1086 | + mkdirSync(dirA, { recursive: true }); |
| 1087 | + mkdirSync(dirB, { recursive: true }); |
| 1088 | + const nodeOptions = `--watch --watch-path=${dirA} --watch-path ${dirB} --no-warnings`; |
| 1089 | + const { done, restart } = runInBackground({ |
| 1090 | + args: ['--watch', file], |
| 1091 | + options: { |
| 1092 | + env: { ...process.env, NODE_OPTIONS: nodeOptions }, |
| 1093 | + }, |
| 1094 | + }); |
| 1095 | + |
| 1096 | + try { |
| 1097 | + const { stdout, stderr } = await restart(); |
| 1098 | + |
| 1099 | + assert.strictEqual(stderr, ''); |
| 1100 | + assert.ok(stdout.some((line) => line === '--no-warnings')); |
| 1101 | + } finally { |
| 1102 | + await done(); |
| 1103 | + } |
| 1104 | + }); |
996 | 1105 | }); |
0 commit comments