mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-02 07:43:42 +08:00
`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.
28 lines
1.1 KiB
TypeScript
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));
|