From 16dd55b9d2092293372142f6f49541068b79465a Mon Sep 17 00:00:00 2001 From: Madhav Majumdar <161720210+madhav2348@users.noreply.github.com> Date: Wed, 4 Jun 2025 09:59:48 +0530 Subject: [PATCH 1/5] migrate param_validator from zod3 to zod 4 - line 325 schema `items` can be access within `def` - line 356 and 360 `_def` is deprecated , use `def` or directly use `options` - line 393 `zodErrorObj.errors[0]` changes to `zodErrorObj.errors[0]` - line 410 `union error` changes to `errors` - line 414 and 459 , `received` changes to `message` ## Important In constants.js, Symbols aren't considered literal values, nor can they be simply compared with ===. This was an oversight in Zod 3. --- src/core/friendly_errors/param_validator.js | 25 ++++++++++++--------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/core/friendly_errors/param_validator.js b/src/core/friendly_errors/param_validator.js index d4fc78830a..aec283e777 100644 --- a/src/core/friendly_errors/param_validator.js +++ b/src/core/friendly_errors/param_validator.js @@ -3,7 +3,7 @@ * @requires core */ import * as constants from '../constants.js'; -import * as z from 'zod'; +import { z } from 'zod/v4'; import dataDoc from '../../../docs/parameterData.json'; function validateParams(p5, fn, lifecycles) { @@ -230,6 +230,10 @@ function validateParams(p5, fn, lifecycles) { param = param?.replace(/^\.\.\.(.+)\[\]$/, '$1'); let schema = generateTypeSchema(param); + if (!schema || typeof schema.optional !== 'function') { + schema = z.any(); + } + if (isOptional) { schema = schema.optional(); } @@ -318,7 +322,7 @@ function validateParams(p5, fn, lifecycles) { } const numArgs = args.length; - const schemaItems = schema.items; + const schemaItems = schema.def.items; const numSchemaItems = schemaItems.length; const numRequiredSchemaItems = schemaItems.filter(item => !item.isOptional()).length; @@ -353,11 +357,11 @@ function validateParams(p5, fn, lifecycles) { }; // Default to the first schema, so that we are guaranteed to return a result. - let closestSchema = schema._def.options[0]; + let closestSchema = schema.def.options[0]; // We want to return the schema with the lowest score. let bestScore = Infinity; - const schemaUnion = schema._def.options; + const schemaUnion = schema.def.options; schemaUnion.forEach(schema => { const score = scoreSchema(schema); if (score < bestScore) { @@ -386,7 +390,7 @@ function validateParams(p5, fn, lifecycles) { // (after scoring the schema closeness in `findClosestSchema`). Here, we // always print the first error so that user can work through the errors // one by one. - let currentError = zodErrorObj.errors[0]; + let currentError = zodErrorObj.issues[0]; // Helper function to build a type mismatch message. const buildTypeMismatchMessage = (actualType, expectedTypeStr, position) => { @@ -403,11 +407,11 @@ function validateParams(p5, fn, lifecycles) { const expectedTypes = new Set(); let actualType; - error.unionErrors.forEach(err => { - const issue = err.issues[0]; + error.errors.forEach(err => { + const issue = err[0]; if (issue) { if (!actualType) { - actualType = issue.received; + actualType = issue.message; } if (issue.code === 'invalid_type') { @@ -416,8 +420,9 @@ function validateParams(p5, fn, lifecycles) { // 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_literal') { + else if (issue.code === 'invalid_value') { 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]); @@ -452,7 +457,7 @@ function validateParams(p5, fn, lifecycles) { break; } case 'invalid_type': { - message += buildTypeMismatchMessage(currentError.received, currentError.expected, currentError.path.join('.')); + message += buildTypeMismatchMessage(currentError.message, currentError.expected, currentError.path.join('.')); break; } case 'too_big': { From bb0c54868a6f0f60a0c8af7d0ed328c2fd2700ba Mon Sep 17 00:00:00 2001 From: Madhav Majumdar <161720210+madhav2348@users.noreply.github.com> Date: Wed, 4 Jun 2025 10:01:42 +0530 Subject: [PATCH 2/5] Update test case of param_validator in param_errors According to zod 4 , error message are more elaborated --- test/unit/core/param_errors.js | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/test/unit/core/param_errors.js b/test/unit/core/param_errors.js index e2bfb7c617..f5602511cb 100644 --- a/test/unit/core/param_errors.js +++ b/test/unit/core/param_errors.js @@ -110,10 +110,10 @@ suite('Validate Params', function () { const invalidInputs = [ { name: 'missing required arc parameters #4, #5', input: [200, 100, 100, 80], msg: '🌸 p5.js says: Expected at least 6 arguments, but received fewer in p5.arc(). For more information, see https://p5js.org/reference/p5/arc.' }, - { name: 'missing required param #0', input: [undefined, 100, 100, 80, 0, Math.PI, constants.PIE, 30], msg: '🌸 p5.js says: Expected number at the first parameter, but received undefined in p5.arc().' }, - { name: 'missing required param #4', input: [200, 100, 100, 80, undefined, 0], msg: '🌸 p5.js says: Expected number at the fifth parameter, but received undefined in p5.arc().' }, - { name: 'missing optional param #5', input: [200, 100, 100, 80, 0, undefined, Math.PI], msg: '🌸 p5.js says: Expected number at the sixth parameter, but received undefined in p5.arc().' }, - { name: 'wrong param type at #0', input: ['a', 100, 100, 80, 0, Math.PI, constants.PIE, 30], msg: '🌸 p5.js says: Expected number at the first parameter, but received string in p5.arc().' } + { name: 'missing required param #0', input: [undefined, 100, 100, 80, 0, Math.PI, constants.PIE, 30], msg: '🌸 p5.js says: Expected number at the first parameter, but received Invalid input: expected number, received undefined in p5.arc().' }, + { name: 'missing required param #4', input: [200, 100, 100, 80, undefined, 0], msg: '🌸 p5.js says: Expected number at the fifth parameter, but received Invalid input: expected number, received undefined in p5.arc().' }, + { name: 'missing optional param #5', input: [200, 100, 100, 80, 0, undefined, Math.PI], msg: '🌸 p5.js says: Expected number at the sixth parameter, but received Invalid input: expected number, received undefined in p5.arc().' }, + { name: 'wrong param type at #0', input: ['a', 100, 100, 80, 0, Math.PI, constants.PIE, 30], msg: '🌸 p5.js says: Expected number at the first parameter, but received Invalid input: expected number, received string in p5.arc().' } ]; invalidInputs.forEach(({ name, input, msg }) => { @@ -130,7 +130,7 @@ suite('Validate Params', function () { console.log(result); assert.equal( result.error, - '🌸 p5.js says: Did you mean to put `await` before a loading function? An unexpected Promise was found. Expected Image or Element or Texture or Framebuffer or FramebufferTexture or Renderer or Graphics at the first parameter in p5.image().' + '🌸 p5.js says: Did you mean to put `await` before a loading function? An unexpected Promise was found. Expected Image or Element or Texture or Framebuffer or FramebufferTexture or Renderer or Graphics at the first parameter, but received Input not instance of Image in p5.image().' ); }); }); @@ -144,13 +144,13 @@ suite('Validate Params', function () { suite('validateParams: a few edge cases', function () { const invalidInputs = [ - { fn: 'color', name: 'wrong type for optional parameter', input: [0, 0, 0, 'A'], msg: '🌸 p5.js says: Expected number at the fourth parameter, but received string in p5.color().' }, - { fn: 'color', name: 'superfluous parameter', input: [[0, 0, 0], 0], msg: '🌸 p5.js says: Expected number at the first parameter, but received array in p5.color().' }, - { fn: 'color', name: 'wrong element types', input: [['A', 'B', 'C']], msg: '🌸 p5.js says: Expected number at the first parameter, but received array in p5.color().' }, - { fn: 'rect', name: 'null, non-trailing, optional parameter', input: [0, 0, 0, 0, null, 0, 0, 0], msg: '🌸 p5.js says: Expected number at the fifth parameter, but received null in p5.rect().' }, + { fn: 'color', name: 'wrong type for optional parameter', input: [0, 0, 0, 'A'], msg: '🌸 p5.js says: Expected number at the fourth parameter, but received Invalid input: expected number, received string in p5.color().' }, + { fn: 'color', name: 'superfluous parameter', input: [[0, 0, 0], 0], msg: '🌸 p5.js says: Expected number at the first parameter, but received Invalid input: expected number, received array in p5.color().' }, + { fn: 'color', name: 'wrong element types', input: [['A', 'B', 'C']], msg: '🌸 p5.js says: Expected number at the first parameter, but received Invalid input: expected number, received array in p5.color().' }, + { fn: 'rect', name: 'null, non-trailing, optional parameter', input: [0, 0, 0, 0, null, 0, 0, 0], msg: '🌸 p5.js says: Expected number at the fifth parameter, but received Invalid input: expected number, received null in p5.rect().' }, { fn: 'color', name: 'too many args + wrong types too', input: ['A', 'A', 0, 0, 0, 0, 0, 0, 0, 0], msg: '🌸 p5.js says: Expected at most 4 arguments, but received more in p5.color(). For more information, see https://p5js.org/reference/p5/color.' }, - { fn: 'line', name: 'null string given', input: [1, 2, 4, 'null'], msg: '🌸 p5.js says: Expected number at the fourth parameter, but received string in p5.line().' }, - { fn: 'line', name: 'NaN value given', input: [1, 2, 4, NaN], msg: '🌸 p5.js says: Expected number at the fourth parameter, but received nan in p5.line().' } + { fn: 'line', name: 'null string given', input: [1, 2, 4, 'null'], msg: '🌸 p5.js says: Expected number at the fourth parameter, but received Invalid input: expected number, received string in p5.line().' }, + { fn: 'line', name: 'NaN value given', input: [1, 2, 4, NaN], msg: '🌸 p5.js says: Expected number at the fourth parameter, but received Invalid input: expected number, received NaN in p5.line().' } ]; invalidInputs.forEach(({ name, input, fn, msg }) => { @@ -163,12 +163,12 @@ suite('Validate Params', function () { suite('validateParams: trailing undefined arguments', function () { const invalidInputs = [ - { fn: 'color', name: 'missing params #1, #2', input: [12, undefined, undefined], msg: '🌸 p5.js says: Expected number at the second parameter, but received undefined in p5.color().' }, + { fn: 'color', name: 'missing params #1, #2', input: [12, undefined, undefined], msg: '🌸 p5.js says: Expected number at the second parameter, but received Invalid input: expected number, received undefined in p5.color().' }, // Even though the undefined arguments are technically allowed for // optional parameters, it is more likely that the user wanted to call // the function with meaningful arguments. { fn: 'random', name: 'missing params #0, #1', input: [undefined, undefined], msg: '🌸 p5.js says: All arguments for p5.random() are undefined. There is likely an error in the code.' }, - { fn: 'circle', name: 'missing compulsory parameter #2', input: [5, 5, undefined], msg: '🌸 p5.js says: Expected number at the third parameter, but received undefined in p5.circle().' } + { fn: 'circle', name: 'missing compulsory parameter #2', input: [5, 5, undefined], msg: '🌸 p5.js says: Expected number at the third parameter, but received Invalid input: expected number, received undefined in p5.circle().' } ]; invalidInputs.forEach(({ fn, name, input, msg }) => { @@ -193,9 +193,9 @@ suite('Validate Params', function () { }); const invalidInputs = [ - { name: 'optional parameter, incorrect type', input: [65, 100, 100, 'a'], msg: '🌸 p5.js says: Expected number at the fourth parameter, but received string in p5.color().' }, - { name: 'extra parameter', input: [[65, 100, 100], 100], msg: '🌸 p5.js says: Expected number at the first parameter, but received array in p5.color().' }, - { name: 'incorrect element type', input: ['A', 'B', 'C'], msg: '🌸 p5.js says: Expected number at the first parameter, but received string in p5.color().' }, + { name: 'optional parameter, incorrect type', input: [65, 100, 100, 'a'], msg: '🌸 p5.js says: Expected number at the fourth parameter, but received Invalid input: expected number, received string in p5.color().' }, + { name: 'extra parameter', input: [[65, 100, 100], 100], msg: '🌸 p5.js says: Expected number at the first parameter, but received Invalid input: expected number, received array in p5.color().' }, + { name: 'incorrect element type', input: ['A', 'B', 'C'], msg: '🌸 p5.js says: Expected number at the first parameter, but received Invalid input: expected number, received string in p5.color().' }, { name: 'incorrect parameter count', input: ['A', 'A', 0, 0, 0, 0, 0, 0], msg: '🌸 p5.js says: Expected at most 4 arguments, but received more in p5.color(). For more information, see https://p5js.org/reference/p5/color.' } ]; @@ -223,7 +223,7 @@ suite('Validate Params', function () { test(`set() with Boolean (invalid)`, function () { const result = mockP5Prototype.validate('p5.set', [0, 0, true]); - assert.equal(result.error, '🌸 p5.js says: Expected number or array or object at the third parameter, but received boolean in p5.set().'); + assert.equal(result.error, '🌸 p5.js says: Expected number or array or object at the third parameter, but received Invalid input: expected number, received boolean in p5.set().'); }); }); From d5b08c2a938f7e1b6676c6ab28c7a2aa768f3a98 Mon Sep 17 00:00:00 2001 From: Madhav Majumdar <161720210+madhav2348@users.noreply.github.com> Date: Thu, 5 Jun 2025 01:09:36 +0530 Subject: [PATCH 3/5] update zod package version --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5ecaee9e0e..3b8f9bd847 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "omggif": "^1.0.10", "pako": "^2.1.0", "pixelmatch": "^7.1.0", - "zod": "^3.23.8" + "zod": "^3.25.51" }, "devDependencies": { "@rollup/plugin-alias": "^5.1.1", @@ -11918,9 +11918,9 @@ } }, "node_modules/zod": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", - "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", + "version": "3.25.51", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.51.tgz", + "integrity": "sha512-TQSnBldh+XSGL+opiSIq0575wvDPqu09AqWe1F7JhUMKY+M91/aGlK4MhpVNO7MgYfHcVCB1ffwAUTJzllKJqg==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/package.json b/package.json index 3ee0dad7ee..ce83c2fce9 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "omggif": "^1.0.10", "pako": "^2.1.0", "pixelmatch": "^7.1.0", - "zod": "^3.23.8" + "zod": "^3.25.51" }, "devDependencies": { "@rollup/plugin-alias": "^5.1.1", From b9ab4681782b8d27ded3132bb0098f1ea5eb7de2 Mon Sep 17 00:00:00 2001 From: Madhav Majumdar <161720210+madhav2348@users.noreply.github.com> Date: Fri, 6 Jun 2025 16:35:40 +0530 Subject: [PATCH 4/5] revert test case of param_validator to match the test cases - split the error messages, to get a type in line 418 and 462 - `actualType` will never be undefined which is checked in line 394 so make it undefined in line 430 to pass all test cases --- src/core/friendly_errors/param_validator.js | 4 ++- test/unit/core/param_errors.js | 36 ++++++++++----------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/core/friendly_errors/param_validator.js b/src/core/friendly_errors/param_validator.js index aec283e777..1ec2f00354 100644 --- a/src/core/friendly_errors/param_validator.js +++ b/src/core/friendly_errors/param_validator.js @@ -415,6 +415,7 @@ function validateParams(p5, fn, lifecycles) { } 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 @@ -426,6 +427,7 @@ function validateParams(p5, fn, lifecycles) { } else if (issue.code === 'custom') { const match = issue.message.match(/Input not instance of (\w+)/); if (match) expectedTypes.add(match[1]); + actualType = undefined } } }); @@ -457,7 +459,7 @@ function validateParams(p5, fn, lifecycles) { break; } case 'invalid_type': { - message += buildTypeMismatchMessage(currentError.message, currentError.expected, currentError.path.join('.')); + message += buildTypeMismatchMessage(currentError.message.split(', received ')[1], currentError.expected, currentError.path.join('.')); break; } case 'too_big': { diff --git a/test/unit/core/param_errors.js b/test/unit/core/param_errors.js index f5602511cb..26a9efe4fb 100644 --- a/test/unit/core/param_errors.js +++ b/test/unit/core/param_errors.js @@ -110,10 +110,10 @@ suite('Validate Params', function () { const invalidInputs = [ { name: 'missing required arc parameters #4, #5', input: [200, 100, 100, 80], msg: '🌸 p5.js says: Expected at least 6 arguments, but received fewer in p5.arc(). For more information, see https://p5js.org/reference/p5/arc.' }, - { name: 'missing required param #0', input: [undefined, 100, 100, 80, 0, Math.PI, constants.PIE, 30], msg: '🌸 p5.js says: Expected number at the first parameter, but received Invalid input: expected number, received undefined in p5.arc().' }, - { name: 'missing required param #4', input: [200, 100, 100, 80, undefined, 0], msg: '🌸 p5.js says: Expected number at the fifth parameter, but received Invalid input: expected number, received undefined in p5.arc().' }, - { name: 'missing optional param #5', input: [200, 100, 100, 80, 0, undefined, Math.PI], msg: '🌸 p5.js says: Expected number at the sixth parameter, but received Invalid input: expected number, received undefined in p5.arc().' }, - { name: 'wrong param type at #0', input: ['a', 100, 100, 80, 0, Math.PI, constants.PIE, 30], msg: '🌸 p5.js says: Expected number at the first parameter, but received Invalid input: expected number, received string in p5.arc().' } + { name: 'missing required param #0', input: [undefined, 100, 100, 80, 0, Math.PI, constants.PIE, 30], msg: '🌸 p5.js says: Expected number at the first parameter, but received undefined in p5.arc().' }, + { name: 'missing required param #4', input: [200, 100, 100, 80, undefined, 0], msg: '🌸 p5.js says: Expected number at the fifth parameter, but received undefined in p5.arc().' }, + { name: 'missing optional param #5', input: [200, 100, 100, 80, 0, undefined, Math.PI], msg: '🌸 p5.js says: Expected number at the sixth parameter, but received undefined in p5.arc().' }, + { name: 'wrong param type at #0', input: ['a', 100, 100, 80, 0, Math.PI, constants.PIE, 30], msg: '🌸 p5.js says: Expected number at the first parameter, but received string in p5.arc().' } ]; invalidInputs.forEach(({ name, input, msg }) => { @@ -130,7 +130,7 @@ suite('Validate Params', function () { console.log(result); assert.equal( result.error, - '🌸 p5.js says: Did you mean to put `await` before a loading function? An unexpected Promise was found. Expected Image or Element or Texture or Framebuffer or FramebufferTexture or Renderer or Graphics at the first parameter, but received Input not instance of Image in p5.image().' + '🌸 p5.js says: Did you mean to put `await` before a loading function? An unexpected Promise was found. Expected Image or Element or Texture or Framebuffer or FramebufferTexture or Renderer or Graphics at the first parameter in p5.image().' ); }); }); @@ -144,13 +144,13 @@ suite('Validate Params', function () { suite('validateParams: a few edge cases', function () { const invalidInputs = [ - { fn: 'color', name: 'wrong type for optional parameter', input: [0, 0, 0, 'A'], msg: '🌸 p5.js says: Expected number at the fourth parameter, but received Invalid input: expected number, received string in p5.color().' }, - { fn: 'color', name: 'superfluous parameter', input: [[0, 0, 0], 0], msg: '🌸 p5.js says: Expected number at the first parameter, but received Invalid input: expected number, received array in p5.color().' }, - { fn: 'color', name: 'wrong element types', input: [['A', 'B', 'C']], msg: '🌸 p5.js says: Expected number at the first parameter, but received Invalid input: expected number, received array in p5.color().' }, - { fn: 'rect', name: 'null, non-trailing, optional parameter', input: [0, 0, 0, 0, null, 0, 0, 0], msg: '🌸 p5.js says: Expected number at the fifth parameter, but received Invalid input: expected number, received null in p5.rect().' }, + { fn: 'color', name: 'wrong type for optional parameter', input: [0, 0, 0, 'A'], msg: '🌸 p5.js says: Expected number at the fourth parameter, but received string in p5.color().' }, + { fn: 'color', name: 'superfluous parameter', input: [[0, 0, 0], 0], msg: '🌸 p5.js says: Expected number at the first parameter, but received array in p5.color().' }, + { fn: 'color', name: 'wrong element types', input: [['A', 'B', 'C']], msg: '🌸 p5.js says: Expected number at the first parameter, but received array in p5.color().' }, + { fn: 'rect', name: 'null, non-trailing, optional parameter', input: [0, 0, 0, 0, null, 0, 0, 0], msg: '🌸 p5.js says: Expected number at the fifth parameter, but received null in p5.rect().' }, { fn: 'color', name: 'too many args + wrong types too', input: ['A', 'A', 0, 0, 0, 0, 0, 0, 0, 0], msg: '🌸 p5.js says: Expected at most 4 arguments, but received more in p5.color(). For more information, see https://p5js.org/reference/p5/color.' }, - { fn: 'line', name: 'null string given', input: [1, 2, 4, 'null'], msg: '🌸 p5.js says: Expected number at the fourth parameter, but received Invalid input: expected number, received string in p5.line().' }, - { fn: 'line', name: 'NaN value given', input: [1, 2, 4, NaN], msg: '🌸 p5.js says: Expected number at the fourth parameter, but received Invalid input: expected number, received NaN in p5.line().' } + { fn: 'line', name: 'null string given', input: [1, 2, 4, 'null'], msg: '🌸 p5.js says: Expected number at the fourth parameter, but received string in p5.line().' }, + { fn: 'line', name: 'NaN value given', input: [1, 2, 4, NaN], msg: '🌸 p5.js says: Expected number at the fourth parameter, but received NaN in p5.line().' } ]; invalidInputs.forEach(({ name, input, fn, msg }) => { @@ -163,12 +163,12 @@ suite('Validate Params', function () { suite('validateParams: trailing undefined arguments', function () { const invalidInputs = [ - { fn: 'color', name: 'missing params #1, #2', input: [12, undefined, undefined], msg: '🌸 p5.js says: Expected number at the second parameter, but received Invalid input: expected number, received undefined in p5.color().' }, + { fn: 'color', name: 'missing params #1, #2', input: [12, undefined, undefined], msg: '🌸 p5.js says: Expected number at the second parameter, but received undefined in p5.color().' }, // Even though the undefined arguments are technically allowed for // optional parameters, it is more likely that the user wanted to call // the function with meaningful arguments. { fn: 'random', name: 'missing params #0, #1', input: [undefined, undefined], msg: '🌸 p5.js says: All arguments for p5.random() are undefined. There is likely an error in the code.' }, - { fn: 'circle', name: 'missing compulsory parameter #2', input: [5, 5, undefined], msg: '🌸 p5.js says: Expected number at the third parameter, but received Invalid input: expected number, received undefined in p5.circle().' } + { fn: 'circle', name: 'missing compulsory parameter #2', input: [5, 5, undefined], msg: '🌸 p5.js says: Expected number at the third parameter, but received undefined in p5.circle().' } ]; invalidInputs.forEach(({ fn, name, input, msg }) => { @@ -193,9 +193,9 @@ suite('Validate Params', function () { }); const invalidInputs = [ - { name: 'optional parameter, incorrect type', input: [65, 100, 100, 'a'], msg: '🌸 p5.js says: Expected number at the fourth parameter, but received Invalid input: expected number, received string in p5.color().' }, - { name: 'extra parameter', input: [[65, 100, 100], 100], msg: '🌸 p5.js says: Expected number at the first parameter, but received Invalid input: expected number, received array in p5.color().' }, - { name: 'incorrect element type', input: ['A', 'B', 'C'], msg: '🌸 p5.js says: Expected number at the first parameter, but received Invalid input: expected number, received string in p5.color().' }, + { name: 'optional parameter, incorrect type', input: [65, 100, 100, 'a'], msg: '🌸 p5.js says: Expected number at the fourth parameter, but received string in p5.color().' }, + { name: 'extra parameter', input: [[65, 100, 100], 100], msg: '🌸 p5.js says: Expected number at the first parameter, but received array in p5.color().' }, + { name: 'incorrect element type', input: ['A', 'B', 'C'], msg: '🌸 p5.js says: Expected number at the first parameter, but received string in p5.color().' }, { name: 'incorrect parameter count', input: ['A', 'A', 0, 0, 0, 0, 0, 0], msg: '🌸 p5.js says: Expected at most 4 arguments, but received more in p5.color(). For more information, see https://p5js.org/reference/p5/color.' } ]; @@ -223,7 +223,7 @@ suite('Validate Params', function () { test(`set() with Boolean (invalid)`, function () { const result = mockP5Prototype.validate('p5.set', [0, 0, true]); - assert.equal(result.error, '🌸 p5.js says: Expected number or array or object at the third parameter, but received Invalid input: expected number, received boolean in p5.set().'); + assert.equal(result.error, '🌸 p5.js says: Expected number or array or object at the third parameter, but received boolean in p5.set().'); }); }); @@ -278,4 +278,4 @@ suite('Validate Params', function () { assert.isFalse(result.success); }); }); -}); +}); \ No newline at end of file From 495903ee37aa2b33f3dab8f3e69c778e008a7b82 Mon Sep 17 00:00:00 2001 From: Madhav Majumdar <161720210+madhav2348@users.noreply.github.com> Date: Fri, 13 Jun 2025 15:51:48 +0530 Subject: [PATCH 5/5] update schema type check for zod function - z.function() is no longer a Zod schema. Instead, it acts as a standalone "function factory" for defining Zod-validated functions. - .def.type checks schema type. If its `'function'`, fallback to `z.any()` --- src/core/friendly_errors/param_validator.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/friendly_errors/param_validator.js b/src/core/friendly_errors/param_validator.js index 1ec2f00354..61f8f769fe 100644 --- a/src/core/friendly_errors/param_validator.js +++ b/src/core/friendly_errors/param_validator.js @@ -230,8 +230,8 @@ function validateParams(p5, fn, lifecycles) { param = param?.replace(/^\.\.\.(.+)\[\]$/, '$1'); let schema = generateTypeSchema(param); - if (!schema || typeof schema.optional !== 'function') { - schema = z.any(); + if (schema.def.type === 'function') { + schema = z.any() } if (isOptional) {