Skip to content

Commit e1c8d76

Browse files
davepagureklimzykenneth
authored andcommitted
Handle rest params in FES
1 parent e77dde4 commit e1c8d76

File tree

4 files changed

+51
-15
lines changed

4 files changed

+51
-15
lines changed

docs/parameterData.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1427,7 +1427,7 @@
14271427
"createVector": {
14281428
"overloads": [
14291429
[
1430-
"...Number"
1430+
"...Number[]"
14311431
]
14321432
]
14331433
},

src/core/friendly_errors/param_validator.js

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -226,9 +226,14 @@ function validateParams(p5, fn, lifecycles) {
226226
const isOptional = param?.endsWith('?');
227227
param = param?.replace(/\?$/, '');
228228

229-
let schema = generateTypeSchema(param);
229+
const isRest = param?.startsWith('...') && param?.endsWith('[]');
230+
param = param?.replace(/^\.\.\.(.+)\[\]$/, '$1');
230231

231-
return isOptional ? schema.optional() : schema;
232+
let schema = generateTypeSchema(param);
233+
if (isOptional) {
234+
schema = schema.optional();
235+
}
236+
return { schema, rest: isRest };
232237
};
233238

234239
// Note that in Zod, `optional()` only checks for undefined, not the absence
@@ -262,14 +267,22 @@ function validateParams(p5, fn, lifecycles) {
262267
const overloadSchemas = overloads.flatMap(overload => {
263268
const combinations = generateOverloadCombinations(overload);
264269

265-
return combinations.map(combo =>
266-
z.tuple(
267-
combo
268-
.map(p => generateParamSchema(p))
269-
// For now, ignore schemas that cannot be mapped to a defined type
270-
.filter(schema => schema !== undefined)
271-
)
272-
);
270+
return combinations.map(combo => {
271+
const params = combo
272+
.map(p => generateParamSchema(p))
273+
.filter(s => s.schema !== undefined);
274+
275+
let rest;
276+
if (params.at(-1)?.rest) {
277+
rest = params.pop();
278+
}
279+
280+
let combined = z.tuple(params.map(s => s.schema));
281+
if (rest) {
282+
combined = combined.rest(rest.schema);
283+
}
284+
return combined;
285+
});
273286
});
274287

275288
return overloadSchemas.length === 1
@@ -504,7 +517,7 @@ function validateParams(p5, fn, lifecycles) {
504517
// theoretically allowed to stay undefined and valid, it is likely that the
505518
// user intended to call the function with non-undefined arguments. Skip
506519
// regular workflow and return a friendly error message right away.
507-
if (Array.isArray(args) && args.every(arg => arg === undefined)) {
520+
if (Array.isArray(args) && args.length > 0 && args.every(arg => arg === undefined)) {
508521
const undefinedErrorMessage = `🌸 p5.js says: All arguments for ${func}() are undefined. There is likely an error in the code.`;
509522

510523
return {

test/unit/core/param_errors.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,29 @@ suite('Validate Params', function () {
253253
];
254254
const result = mockP5Prototype.validate('p5.paletteLerp', [colorStops, 0.5]);
255255
assert.isTrue(result.success);
256-
})
257-
})
256+
});
257+
});
258+
259+
suite('validateParams: rest arguments', function () {
260+
test('createVector(): works with no args', function() {
261+
const result = mockP5Prototype.validate('p5.createVector', []);
262+
assert.isTrue(result.success);
263+
});
264+
test('createVector(): works with one number', function() {
265+
const result = mockP5Prototype.validate('p5.createVector', [1]);
266+
assert.isTrue(result.success);
267+
});
268+
test('createVector(): works with many numbers', function() {
269+
const result = mockP5Prototype.validate('p5.createVector', [1, 2, 3, 4]);
270+
assert.isTrue(result.success);
271+
});
272+
test('createVector(): fails with a non-number', function() {
273+
const result = mockP5Prototype.validate('p5.createVector', ['1']);
274+
assert.isFalse(result.success);
275+
});
276+
test('createVector(): fails with any non-number', function() {
277+
const result = mockP5Prototype.validate('p5.createVector', [1, 2, '3', 4]);
278+
assert.isFalse(result.success);
279+
});
280+
});
258281
});

utils/convert.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ function cleanUpClassItems(data) {
534534
type += '?';
535535
}
536536
if (param.rest) {
537-
type = `...${type}`;
537+
type = `...${type}[]`;
538538
}
539539
return type;
540540
}

0 commit comments

Comments
 (0)