Skip to content

Correct parseNodeArgs and formatNodeOptions processing of NODE_OPTIONS#71759

Open
martinjlowm wants to merge 3 commits intovercel:canaryfrom
martinjlowm:fix/node-options-de-serialization
Open

Correct parseNodeArgs and formatNodeOptions processing of NODE_OPTIONS#71759
martinjlowm wants to merge 3 commits intovercel:canaryfrom
martinjlowm:fix/node-options-de-serialization

Conversation

@martinjlowm
Copy link
Copy Markdown

@martinjlowm martinjlowm commented Oct 23, 2024

This doesn't fix any reported issue - a reproducible link was not applicable for this case hence why I didn't create an issue (sounded like a hard requirement).

What?

--r= is an invalid value if passed to NODE_OPTIONS which could've been the outcome previously from -r file.js, because all options were forcefully prefixed with -- that could lead to such invalid options.

Why?

parseNodeArgs and formatNodeOptions currently does not account for short options that also may have values and not simply be a boolean.

How?

The implementations now uses the token "rawName" to include single or double dashes and accounts for there being repeated options by storing values in an array.

@ijjk
Copy link
Copy Markdown
Member

ijjk commented Oct 23, 2024

Allow CI Workflow Run

  • approve CI run for commit: a987fa7

Note: this should only be enabled once the PR is ready to go and can only be enabled by a maintainer

runderworld added a commit to runderworld/next.js that referenced this pull request Jul 24, 2025
- custom-patches/next+canary.patch: dist-only diff for applying PR vercel#71759 to Next.js canary
- custom-scripts/setup-patch-package.sh: automates installation & wiring of patch-package on npm install
runderworld added a commit to runderworld/next.js that referenced this pull request Jul 24, 2025
- custom-patches/next+canary.patch: dist-only diff for applying PR vercel#71759 to Next.js canary
- custom-scripts/setup-patch-package.sh: automates installation & wiring of patch-package on npm install
runderworld added a commit to runderworld/next.js that referenced this pull request Jul 24, 2025
- custom-patches/next+canary.patch: dist-only diff for applying PR vercel#71759 to Next.js canary
- custom-scripts/setup-patch-package.sh: automates installation & wiring of patch-package on npm install
runderworld added a commit to runderworld/next.js that referenced this pull request Jul 24, 2025
- custom-patches/next+canary.patch: dist-only diff for applying PR vercel#71759 to Next.js canary
- custom-scripts/setup-patch-package.sh: automates installation & wiring of patch-package on npm install
runderworld added a commit to runderworld/next.js that referenced this pull request Jul 24, 2025
- custom-patches/next+canary.patch: dist-only diff for applying PR vercel#71759 to Next.js canary
- custom-scripts/setup-patch-package.sh: automates installation & wiring of patch-package on npm install
runderworld added a commit to runderworld/next.js that referenced this pull request Aug 30, 2025
- custom-patches/next+canary.patch: dist-only diff for applying PR vercel#71759 to Next.js canary
- custom-scripts/setup-patch-package.sh: automates installation & wiring of patch-package on npm install
@runderworld
Copy link
Copy Markdown

@martinjlowm I updated your PR in my fork to be compatible with canary: runderworld/next.js@patch-pr71759++. Feel free to cherry-pick or merge from it if helpful. Let me know if you'd prefer a separate PR instead. CC @icyJoseph

Comment on lines +188 to +208
.map(([key, values]) => {
return values
.map((value) => {
if (value === true) {
return key
}

if (value) {
// Values with spaces need to be quoted. We use JSON.stringify to
// also escape any nested quotes.
const encodedValue =
value.includes(' ') && !value.startsWith('"')
? JSON.stringify(value)
: value

return `${key}${key.startsWith('--') ? '=' : ' '}${encodedValue}`
}

return null
})
.join(' ')
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logic error in nested array processing: The inner map operation on line 190 can return null values (line 206), but these nulls are joined with spaces (line 208) before being filtered out (line 211). This will create strings with extra spaces like 'option1 option3' when null values are joined. The filter should be applied to each inner array before joining, not after the outer join.

Suggested change
.map(([key, values]) => {
return values
.map((value) => {
if (value === true) {
return key
}
if (value) {
// Values with spaces need to be quoted. We use JSON.stringify to
// also escape any nested quotes.
const encodedValue =
value.includes(' ') && !value.startsWith('"')
? JSON.stringify(value)
: value
return `${key}${key.startsWith('--') ? '=' : ' '}${encodedValue}`
}
return null
})
.join(' ')
.map(([key, values]) => {
return values
.map((value) => {
if (value === true) {
return key
}
if (value) {
// Values with spaces need to be quoted. We use JSON.stringify to
// also escape any nested quotes.
const encodedValue =
value.includes(' ') && !value.startsWith('"')
? JSON.stringify(value)
: value
return `${key}${key.startsWith('--') ? '=' : ' '}${encodedValue}`
}
return null
})
.filter(Boolean)
.join(' ')

Spotted by Diamond

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

runderworld added a commit to runderworld/next.js that referenced this pull request Dec 5, 2025
- custom-patches/next+canary.patch: dist-only diff for applying PR vercel#71759 to Next.js canary
- custom-scripts/setup-patch-package.sh: automates installation & wiring of patch-package on npm install
runderworld added a commit to runderworld/next.js that referenced this pull request Feb 13, 2026
…PTIONS

Fixes vercel#77550 — Port of PR vercel#71759 to v16.x (canary).

The core issue: parseNodeArgs used node:util parseArgs which strips dash
prefixes and deduplicates keys. When NODE_OPTIONS contains repeated short
options like '-r file1.js -r file2.js', the old code lost values and
formatNodeOptions forced '--' prefix on everything (turning '-r' into
'--r=', which is invalid in NODE_OPTIONS).

Changes:
- parseNodeArgs now uses token.rawName to preserve '-' vs '--' prefixes
  and stores values as arrays to support repeated options
- Introduced NodeOptions class wrapping the parsed result with get/set/
  delete/has/clone/raw helpers for clean caller interaction
- formatNodeOptions updated to handle array values and use the correct
  separator ('=' for long options, ' ' for short options)
- Updated callers in next-dev.ts and worker.ts to use NodeOptions methods
- Added tests for repeated -r/--require options (short and long forms),
  short option formatting, repeated option formatting, and boolean options
- Applied Graphite bot suggestion: filter(Boolean) before join in inner
  map to avoid extra spaces from null values
runderworld added a commit to runderworld/next.js that referenced this pull request Feb 13, 2026
…PTIONS

Fixes vercel#77550 — Port of PR vercel#71759 to v16.x (canary).

The core issue: parseNodeArgs used node:util parseArgs which strips dash
prefixes and deduplicates keys. When NODE_OPTIONS contains repeated short
options like '-r file1.js -r file2.js', the old code lost values and
formatNodeOptions forced '--' prefix on everything (turning '-r' into
'--r=', which is invalid in NODE_OPTIONS).

Changes:
- parseNodeArgs now uses token.rawName to preserve '-' vs '--' prefixes
  and stores values as arrays to support repeated options
- Introduced NodeOptions class wrapping the parsed result with get/set/
  delete/has/clone/raw helpers for clean caller interaction
- formatNodeOptions updated to handle array values and use the correct
  separator ('=' for long options, ' ' for short options)
- Updated callers in next-dev.ts and worker.ts to use NodeOptions methods
- Added tests for repeated -r/--require options (short and long forms),
  short option formatting, repeated option formatting, and boolean options
- Applied Graphite bot suggestion: filter(Boolean) before join in inner
  map to avoid extra spaces from null values
runderworld added a commit to runderworld/next.js that referenced this pull request Feb 13, 2026
…PTIONS

Fixes vercel#77550 — Port of PR vercel#71759 to v16.x (canary).

The core issue: parseNodeArgs used node:util parseArgs which strips dash
prefixes and deduplicates keys. When NODE_OPTIONS contains repeated short
options like '-r file1.js -r file2.js', the old code lost values and
formatNodeOptions forced '--' prefix on everything (turning '-r' into
'--r=', which is invalid in NODE_OPTIONS).

Changes:
- parseNodeArgs now uses token.rawName to preserve '-' vs '--' prefixes
  and stores values as arrays to support repeated options
- Introduced NodeOptions class wrapping the parsed result with get/set/
  delete/has/clone/raw helpers for clean caller interaction
- formatNodeOptions updated to handle array values and use the correct
  separator ('=' for long options, ' ' for short options)
- Updated callers in next-dev.ts and worker.ts to use NodeOptions methods
- Added tests for repeated -r/--require options (short and long forms),
  short option formatting, repeated option formatting, and boolean options
- Applied Graphite bot suggestion: filter(Boolean) before join in inner
  map to avoid extra spaces from null values
runderworld added a commit to runderworld/next.js that referenced this pull request Feb 21, 2026
…PTIONS

Fixes vercel#77550 — Port of PR vercel#71759 to v16.x (canary).

The core issue: parseNodeArgs used node:util parseArgs which strips dash
prefixes and deduplicates keys. When NODE_OPTIONS contains repeated short
options like '-r file1.js -r file2.js', the old code lost values and
formatNodeOptions forced '--' prefix on everything (turning '-r' into
'--r=', which is invalid in NODE_OPTIONS).

Changes:
- parseNodeArgs now uses token.rawName to preserve '-' vs '--' prefixes
  and stores values as arrays to support repeated options
- Introduced NodeOptions class wrapping the parsed result with get/set/
  delete/has/clone/raw helpers for clean caller interaction
- formatNodeOptions updated to handle array values and use the correct
  separator ('=' for long options, ' ' for short options)
- Updated callers in next-dev.ts and worker.ts to use NodeOptions methods
- Added tests for repeated -r/--require options (short and long forms),
  short option formatting, repeated option formatting, and boolean options
- Applied Graphite bot suggestion: filter(Boolean) before join in inner
  map to avoid extra spaces from null values
runderworld added a commit to runderworld/next.js that referenced this pull request Feb 21, 2026
…PTIONS

Fixes vercel#77550 — Port of PR vercel#71759 to v16.x (canary).

The core issue: parseNodeArgs used node:util parseArgs which strips dash
prefixes and deduplicates keys. When NODE_OPTIONS contains repeated short
options like '-r file1.js -r file2.js', the old code lost values and
formatNodeOptions forced '--' prefix on everything (turning '-r' into
'--r=', which is invalid in NODE_OPTIONS).

Changes:
- parseNodeArgs now uses token.rawName to preserve '-' vs '--' prefixes
  and stores values as arrays to support repeated options
- Introduced NodeOptions class wrapping the parsed result with get/set/
  delete/has/clone/raw helpers for clean caller interaction
- formatNodeOptions updated to handle array values and use the correct
  separator ('=' for long options, ' ' for short options)
- Updated callers in next-dev.ts and worker.ts to use NodeOptions methods
- Added tests for repeated -r/--require options (short and long forms),
  short option formatting, repeated option formatting, and boolean options
- Applied Graphite bot suggestion: filter(Boolean) before join in inner
  map to avoid extra spaces from null values
runderworld added a commit to runderworld/next.js that referenced this pull request Feb 21, 2026
…PTIONS

Fixes vercel#77550 — Port of PR vercel#71759 to v16.x (canary).

The core issue: parseNodeArgs used node:util parseArgs which strips dash
prefixes and deduplicates keys. When NODE_OPTIONS contains repeated short
options like '-r file1.js -r file2.js', the old code lost values and
formatNodeOptions forced '--' prefix on everything (turning '-r' into
'--r=', which is invalid in NODE_OPTIONS).

Changes:
- parseNodeArgs now uses token.rawName to preserve '-' vs '--' prefixes
  and stores values as arrays to support repeated options
- Introduced NodeOptions class wrapping the parsed result with get/set/
  delete/has/clone/raw helpers for clean caller interaction
- formatNodeOptions updated to handle array values and use the correct
  separator ('=' for long options, ' ' for short options)
- Updated callers in next-dev.ts and worker.ts to use NodeOptions methods
- Added tests for repeated -r/--require options (short and long forms),
  short option formatting, repeated option formatting, and boolean options
- Applied Graphite bot suggestion: filter(Boolean) before join in inner
  map to avoid extra spaces from null values
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants