Description
Perry documents the spread operator in calls as supported, and node:path / path.join as supported, but spreading a valid string array into path.join() fails at runtime.
I initially encountered this in a larger application, but it reduces to a very small standalone repro.
Minimal reproduction
repro.ts:
import path from 'node:path';
console.log('direct:', path.join('/tmp/x', 'project.json'));
const parts = ['/tmp/x', 'project.json'];
console.log('spread:', path.join(...parts));
Using Perry 0.5.1220:
pnpm add -D @perryts/perry@0.5.1220
pnpm exec perry compile repro.ts --target linux --output repro
./repro
Actual behavior
The direct call succeeds:
direct: /tmp/x/project.json
The equivalent spread call then throws:
TypeError: The "path" argument must be of type string.
at <anonymous>
and exits nonzero.
Expected behavior
Both forms should be equivalent:
direct: /tmp/x/project.json
spread: /tmp/x/project.json
Node 24.18.0 produces the expected output.
Why I expected this to be supported
The Perry 0.5.1220 README marks:
- functions/rest parameters as supported;
- the spread operator in calls and literals as supported;
path.join as supported.
The runtime parity documentation also lists path.join([...paths]) as supported without a caveat.
Perry's own parity suite contains a spread invocation of path.join in:
test-parity/node-suite/path/join/type-errors-extra.ts
using:
That fixture appears to test invalid argument types, but does not include the corresponding valid-string-array case.
Current main
I also checked current Perry main.
At the time of testing:
commit: 0328a63bbc1b582bfdbb0842a957aac861bd84d7
version: 0.5.1413
I noticed that the current source contains an internal comment in the native-module call lowering code describing:
as a separate runtime spread gap.
That appears to be the same category as:
So this may already be a known implementation limitation internally.
I could not find a corresponding user-facing compatibility caveat or a specific issue tracking this case, and the public compatibility documentation currently appears to describe both spread calls and path.join as supported.
If this gap is already tracked elsewhere, please feel free to close this as a duplicate.
Additional observation
The problem does not require a rest parameter. This also fails:
const parts = ['/tmp/x', 'project.json'];
path.join(...parts);
while this succeeds:
path.join('/tmp/x', 'project.json');
A wrapper using a rest parameter therefore fails for the same reason:
function joinPath(...parts: string[]): string {
return path.join(...parts);
}
Workaround
Avoiding a spread into the native module function works:
function joinPath(...parts: string[]): string {
if (parts.length === 0) {
return '.';
}
let result = parts[0]!;
for (let index = 1; index < parts.length; index += 1) {
result = path.join(result, parts[index]!);
}
return result;
}
Environment
- Perry:
0.5.1220
- Package:
@perryts/perry
- Target:
linux
- Host: Linux x86_64
- Node used to invoke the Perry toolchain:
24.18.0
Description
Perry documents the spread operator in calls as supported, and
node:path/path.joinas supported, but spreading a valid string array intopath.join()fails at runtime.I initially encountered this in a larger application, but it reduces to a very small standalone repro.
Minimal reproduction
repro.ts:Using Perry
0.5.1220:pnpm add -D @perryts/perry@0.5.1220 pnpm exec perry compile repro.ts --target linux --output repro ./reproActual behavior
The direct call succeeds:
The equivalent spread call then throws:
and exits nonzero.
Expected behavior
Both forms should be equivalent:
Node 24.18.0 produces the expected output.
Why I expected this to be supported
The Perry 0.5.1220 README marks:
path.joinas supported.The runtime parity documentation also lists
path.join([...paths])as supported without a caveat.Perry's own parity suite contains a spread invocation of
path.joinin:using:
That fixture appears to test invalid argument types, but does not include the corresponding valid-string-array case.
Current
mainI also checked current Perry
main.At the time of testing:
I noticed that the current source contains an internal comment in the native-module call lowering code describing:
as a separate runtime spread gap.
That appears to be the same category as:
So this may already be a known implementation limitation internally.
I could not find a corresponding user-facing compatibility caveat or a specific issue tracking this case, and the public compatibility documentation currently appears to describe both spread calls and
path.joinas supported.If this gap is already tracked elsewhere, please feel free to close this as a duplicate.
Additional observation
The problem does not require a rest parameter. This also fails:
while this succeeds:
A wrapper using a rest parameter therefore fails for the same reason:
Workaround
Avoiding a spread into the native module function works:
Environment
0.5.1220@perryts/perrylinux24.18.0