Files
scriptc/tests/corpus/7381-function-value-arguments-length.ts
T
Chris Tate aaca1f1e2b Count the arguments a function receives when it is called through a value
`arguments.length` in a typed function folds to a constant. In a function
declaration it was the declared parameter count even when the function is
called through a value with more arguments: Node prints 4 for
`[1].map(f)` with `function f(v) { return v + arguments.length; }`, the
compiled program printed 2.

A top-level function declaration that reads `arguments` and that the
program uses as a value now gets a count slot. Its value is an adapter
that stores the parameter count of the function type the value is passed
as (3 for map, 4 for reduce, 2 for a sort comparator) and forwards; the
function reads the slot on entry and clears it, so a direct call sees the
declared count.

Function expressions and declarations passed where the expected function
type has optional or rest parameters (a replace callback) are called with
a varying count and are refused with SC1090 instead of folding to a wrong
count, as are methods, nested functions, and arrows inside a function
used as a value.
2026-10-22 18:17:48 -05:00

28 lines
1.1 KiB
TypeScript

// `arguments.length` in a function declaration counts the arguments its
// caller passes: a direct call passes the declared parameters, and a call
// through the function as a value passes the parameters of the function
// type it was passed as (3 for map and filter, 4 for reduce, 2 for sort).
function scaled(value: number): number {
return value * 10 + arguments.length;
}
function total(acc: number, value: number): number {
return acc + value + arguments.length;
}
function compare(a: number, b: number): number {
return arguments.length === 2 ? a - b : 0;
}
console.log([1, 2].map(scaled).join(), scaled(3));
console.log([5, 6].filter(scaled).length, [1, 2].reduce(total, 0), total(1, 2));
console.log([3, 1, 2].sort(compare).join());
function apply(f: (a: number, b: number, c: number) => number): number {
return f(1, 2, 3);
}
console.log(apply(scaled));
// A direct call inside a call through the value sees its own count.
function depth(n: number): number {
return n <= 0 ? arguments.length : depth(n - 1) + arguments.length;
}
console.log([2].map(depth).join(), depth(2));