Skip to content
50 changes: 31 additions & 19 deletions src/core/friendly_errors/param_validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ function validateParams(p5, fn, lifecycles) {
'Boolean': z.boolean(),
'Function': z.function(),
'Integer': z.number().int(),
'Number': z.number(),
'Number': z.union([z.number(), z.literal(Infinity), z.literal(-Infinity)]),
'Object': z.object({}),
'String': z.string()
};
Expand Down Expand Up @@ -411,33 +411,44 @@ function validateParams(p5, fn, lifecycles) {
// of any of them. In this case, aggregate all possible types and print
// a friendly error message that indicates what the expected types are at
// which position (position is not 0-indexed, for accessibility reasons).

const processUnionError = error => {
const expectedTypes = new Set();
let actualType;

error.errors.forEach(err => {
const issue = err[0];
if (issue) {
if (!actualType) {
actualType = issue.message;
}
const collectIssue = issue => {
if (!issue) return;
if (!actualType) {
actualType = issue.message;
}

if (issue.code === 'invalid_type') {
actualType = issue.message.split(', received ')[1];
expectedTypes.add(issue.expected);
}
// The case for constants. Since we don't want to print out the actual
// constant values in the error message, the error message will
// direct users to the documentation.
else if (issue.code === 'invalid_value') {
if (issue.code === 'invalid_type') {
actualType = issue.message.split(', received ')[1];
expectedTypes.add(issue.expected);
}
// The case for constants. Since we don't want to print out the actual
// constant values in the error message, the error message will
// direct users to the documentation.
else if (issue.code === 'invalid_value') {
if (Array.isArray(issue.values) && issue.values.every(v => v === Infinity || v === -Infinity)) {
expectedTypes.add('number');
} else {
expectedTypes.add('constant (please refer to documentation for allowed values)');
actualType = args[error.path[0]];
} else if (issue.code === 'custom') {
const match = issue.message.match(/Input not instance of (\w+)/);
if (match) expectedTypes.add(match[1]);
actualType = undefined;
}
} else if (issue.code === 'custom') {
const match = issue.message.match(/Input not instance of (\w+)/);
if (match) expectedTypes.add(match[1]);
actualType = undefined;
} else if (issue.code === 'invalid_union') {
issue.errors.forEach(nestedErr => {
nestedErr.forEach(nestedIssue => collectIssue(nestedIssue));
});
}
};

error.errors.forEach(err => {
err.forEach(issue => collectIssue(issue));
});

if (expectedTypes.size > 0) {
Expand All @@ -458,6 +469,7 @@ function validateParams(p5, fn, lifecycles) {
return message;
};


switch (currentError.code) {
case 'invalid_union': {
processUnionError(currentError);
Expand Down
16 changes: 16 additions & 0 deletions test/unit/math/calculation.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,14 @@ suite('Calculation', function() {
result = mockP5Prototype.max([10, 10]);
assert.equal(result, 10);
});
test('should handle Infinity as a valid argument', function() {
result = mockP5Prototype.max(Infinity, 42);
assert.equal(result, Infinity);
});
test('should handle -Infinity as a valid argument', function() {
result = mockP5Prototype.max(-Infinity, 42);
assert.equal(result, 42);
});
});

suite('p5.prototype.min', function() {
Expand Down Expand Up @@ -331,6 +339,14 @@ suite('Calculation', function() {
result = mockP5Prototype.min([10, 10]);
assert.equal(result, 10);
});
test('should handle Infinity as a valid argument', function() {
result = mockP5Prototype.min(Infinity, 42);
assert.equal(result, 42);
});
test('should handle -Infinity as a valid argument', function() {
result = mockP5Prototype.min(-Infinity, 42);
assert.equal(result, -Infinity);
});
});

suite('p5.prototype.norm', function() {
Expand Down
Loading