diff --git a/src/vm.ts b/src/vm.ts index 0ca7bf9..ab1debe 100644 --- a/src/vm.ts +++ b/src/vm.ts @@ -468,14 +468,6 @@ export class VM { } } - // Handle variadic parameter (TypeScript rest parameters) - // For TypeScript functions with ...rest, we spread the remaining args - // rather than wrapping them in an array - if (paramInfo.variadic) { - const remainingArgs = positionalArgs.slice(nativePositionalArgIndex) - nativeArgs.push(...remainingArgs) - } - // Handle named parameter (collect remaining unmatched named args) // Parameter names matching atXxx pattern (e.g., atOptions, atNamed) collect extra named args if (paramInfo.named) { @@ -488,6 +480,14 @@ export class VM { nativeArgs.push(toValue(namedObj)) } + // Handle variadic parameter (TypeScript rest parameters) + // For TypeScript functions with ...rest, we spread the remaining args + // rather than wrapping them in an array + if (paramInfo.variadic) { + const remainingArgs = positionalArgs.slice(nativePositionalArgIndex) + nativeArgs.push(...remainingArgs) + } + // Call the native function with bound args const result = await fn.fn(...nativeArgs) this.stack.push(result) diff --git a/tests/native.test.ts b/tests/native.test.ts index f750dda..4800c09 100644 --- a/tests/native.test.ts +++ b/tests/native.test.ts @@ -534,6 +534,31 @@ test("@named pattern - basic atNamed parameter", async () => { expect(result).toEqual({ type: 'string', value: 'Hi, Alice! Extra: value' }) }) +test('@named pattern - atNamed parameters with varadic args', async () => { + const bytecode = toBytecode(` + TRY_LOAD cmd + TRY_LOAD rest1 + TRY_LOAD rest2 + PUSH 'named' + TRY_LOAD named-value + PUSH 2 + PUSH 1 + CALL + HALT + `) + + const vm = new VM(bytecode) + vm.registerFunction('cmd', (atNamed: any = {}, ...rest: string[]) => { + return { rest, namedArg: atNamed['named'] } + }) + + const result = await vm.run() + expect(result.type).toBe('dict') + if (!(result.value instanceof Map)) throw new Error('Expected dict') + expect(result.value.get('rest')).toEqual(toValue(['rest1', 'rest2'])) + expect(result.value.get('namedArg')).toEqual(toValue('named-value')) +}) + test("@named pattern - mixed positional and atOptions", async () => { const bytecode = toBytecode(` LOAD configure