From a70083a55ce45756d5f4c31de6607b0bee5b5a09 Mon Sep 17 00:00:00 2001 From: limzykenneth Date: Wed, 18 Dec 2024 17:13:15 +0000 Subject: [PATCH 1/7] Enable new parameter validation through decorator pattern --- src/accessibility/describe.js | 4 +-- src/accessibility/outputs.js | 4 +-- src/app.js | 2 +- src/color/creating_reading.js | 20 +++++++------- src/color/setting.js | 4 +-- src/core/constants.js | 2 +- src/core/environment.js | 6 ++--- src/core/friendly_errors/param_validator.js | 30 ++++++++++++++++----- src/core/rendering.js | 6 ++--- src/core/transform.js | 16 +++++------ src/data/p5.TypedDict.js | 4 +-- src/dom/dom.js | 26 +++++++++--------- src/dom/p5.MediaElement.js | 6 ++--- src/events/acceleration.js | 4 +-- src/events/keyboard.js | 2 +- src/image/image.js | 6 ++--- src/image/loading_displaying.js | 8 +++--- src/image/pixels.js | 12 ++++----- src/io/files.js | 14 +++++----- src/math/calculation.js | 14 +++++----- src/math/random.js | 2 +- src/math/trigonometry.js | 2 +- src/shape/2d_primitives.js | 19 ++++++------- src/shape/attributes.js | 10 +++---- src/shape/curves.js | 16 +++++------ src/shape/vertex.js | 12 ++++----- src/utilities/string_functions.js | 20 +++++++------- src/webgl/3d_primitives.js | 14 +++++----- src/webgl/interaction.js | 4 +-- src/webgl/light.js | 14 +++++----- src/webgl/loading.js | 4 +-- src/webgl/material.js | 24 ++++++++--------- src/webgl/p5.Camera.js | 10 +++---- 33 files changed, 180 insertions(+), 161 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index 5173a101de..de28a74f01 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -118,7 +118,7 @@ function describe(p5, fn){ */ fn.describe = function(text, display) { - p5._validateParameters('describe', arguments); + // p5._validateParameters('describe', arguments); if (typeof text !== 'string') { return; } @@ -244,7 +244,7 @@ function describe(p5, fn){ */ fn.describeElement = function(name, text, display) { - p5._validateParameters('describeElement', arguments); + // p5._validateParameters('describeElement', arguments); if (typeof text !== 'string' || typeof name !== 'string') { return; } diff --git a/src/accessibility/outputs.js b/src/accessibility/outputs.js index 97b38712f4..68ab322a5a 100644 --- a/src/accessibility/outputs.js +++ b/src/accessibility/outputs.js @@ -122,7 +122,7 @@ function outputs(p5, fn){ */ fn.textOutput = function(display) { - p5._validateParameters('textOutput', arguments); + // p5._validateParameters('textOutput', arguments); //if textOutput is already true if (this._accessibleOutputs.text) { return; @@ -257,7 +257,7 @@ function outputs(p5, fn){ */ fn.gridOutput = function(display) { - p5._validateParameters('gridOutput', arguments); + // p5._validateParameters('gridOutput', arguments); //if gridOutput is already true if (this._accessibleOutputs.grid) { return; diff --git a/src/app.js b/src/app.js index 9de84f07f2..c725ad5331 100644 --- a/src/app.js +++ b/src/app.js @@ -1,7 +1,7 @@ // core import p5 from './core/main'; import './core/friendly_errors/stacktrace'; -import './core/friendly_errors/validate_params'; +// import './core/friendly_errors/validate_params'; import './core/friendly_errors/file_errors'; import './core/friendly_errors/fes_core'; import './core/friendly_errors/sketch_reader'; diff --git a/src/color/creating_reading.js b/src/color/creating_reading.js index 976aba3176..9396c0f0a9 100644 --- a/src/color/creating_reading.js +++ b/src/color/creating_reading.js @@ -349,7 +349,7 @@ function creatingReading(p5, fn){ * @return {p5.Color} */ fn.color = function(...args) { - p5._validateParameters('color', args); + // p5._validateParameters('color', args); if (args[0] instanceof Color) { // TODO: perhaps change color mode to match instance mode? return args[0]; // Do nothing if argument is already a color object. @@ -495,7 +495,7 @@ function creatingReading(p5, fn){ * */ fn.red = function(c) { - p5._validateParameters('red', arguments); + // p5._validateParameters('red', arguments); // Get current red max return this.color(c)._getRed(); }; @@ -632,7 +632,7 @@ function creatingReading(p5, fn){ * */ fn.green = function(c) { - p5._validateParameters('green', arguments); + // p5._validateParameters('green', arguments); // Get current green max return this.color(c)._getGreen(); }; @@ -769,7 +769,7 @@ function creatingReading(p5, fn){ * */ fn.blue = function(c) { - p5._validateParameters('blue', arguments); + // p5._validateParameters('blue', arguments); // Get current blue max return this.color(c)._getBlue(); }; @@ -871,7 +871,7 @@ function creatingReading(p5, fn){ * */ fn.alpha = function(c) { - p5._validateParameters('alpha', arguments); + // p5._validateParameters('alpha', arguments); // Get current alpha max return this.color(c)._getAlpha(); }; @@ -993,7 +993,7 @@ function creatingReading(p5, fn){ * */ fn.hue = function(c) { - p5._validateParameters('hue', arguments); + // p5._validateParameters('hue', arguments); return this.color(c)._getHue(); }; @@ -1170,7 +1170,7 @@ function creatingReading(p5, fn){ * */ fn.saturation = function(c) { - p5._validateParameters('saturation', arguments); + // p5._validateParameters('saturation', arguments); return this.color(c)._getSaturation(); }; @@ -1315,7 +1315,7 @@ function creatingReading(p5, fn){ * */ fn.brightness = function(c) { - p5._validateParameters('brightness', arguments); + // p5._validateParameters('brightness', arguments); return this.color(c)._getBrightness(); }; @@ -1460,7 +1460,7 @@ function creatingReading(p5, fn){ * */ fn.lightness = function(c) { - p5._validateParameters('lightness', arguments); + // p5._validateParameters('lightness', arguments); return this.color(c)._getLightness(); }; @@ -1524,7 +1524,7 @@ function creatingReading(p5, fn){ * */ fn.lerpColor = function(c1, c2, amt) { - p5._validateParameters('lerpColor', arguments); + // p5._validateParameters('lerpColor', arguments); return c1.lerp(c2, amt, this._renderer.states.colorMode); }; } diff --git a/src/color/setting.js b/src/color/setting.js index 05f8f684ba..77c31cf25f 100644 --- a/src/color/setting.js +++ b/src/color/setting.js @@ -949,7 +949,7 @@ function setting(p5, fn){ * @return {String} The current color mode. */ fn.colorMode = function(mode, max1, max2, max3, maxA) { - p5._validateParameters('colorMode', arguments); + // p5._validateParameters('colorMode', arguments); if ( [ RGB, @@ -2184,7 +2184,7 @@ function setting(p5, fn){ * */ fn.blendMode = function (mode) { - p5._validateParameters('blendMode', arguments); + // p5._validateParameters('blendMode', arguments); if (mode === constants.NORMAL) { // Warning added 3/26/19, can be deleted in future (1.0 release?) console.warn( diff --git a/src/core/constants.js b/src/core/constants.js index ff9c873433..60d0d1ba09 100644 --- a/src/core/constants.js +++ b/src/core/constants.js @@ -20,7 +20,7 @@ export const VERSION = 'VERSION_WILL_BE_REPLACED_BY_BUILD'; * @property {P2D} P2D * @final */ -export const P2D = Symbol('p2d'); +export const P2D = 'p2d'; export const P2DHDR = 'p2d-hdr'; diff --git a/src/core/environment.js b/src/core/environment.js index fa35c8f7de..1cdb735644 100644 --- a/src/core/environment.js +++ b/src/core/environment.js @@ -407,7 +407,7 @@ function environment(p5, fn){ * @return {Number} current frame rate. */ fn.frameRate = function(fps) { - p5._validateParameters('frameRate', arguments); + // p5._validateParameters('frameRate', arguments); if (typeof fps !== 'number' || fps < 0) { return this._frameRate; } else { @@ -992,7 +992,7 @@ function environment(p5, fn){ * */ fn.fullscreen = function(val) { - p5._validateParameters('fullscreen', arguments); + // p5._validateParameters('fullscreen', arguments); // no arguments, return fullscreen or not if (typeof val === 'undefined') { return ( @@ -1070,7 +1070,7 @@ function environment(p5, fn){ * @returns {Number} current pixel density of the sketch. */ fn.pixelDensity = function(val) { - p5._validateParameters('pixelDensity', arguments); + // p5._validateParameters('pixelDensity', arguments); let returnValue; if (typeof val === 'number') { if (val !== this._renderer._pixelDensity) { diff --git a/src/core/friendly_errors/param_validator.js b/src/core/friendly_errors/param_validator.js index 27a5420695..a81b1d1409 100644 --- a/src/core/friendly_errors/param_validator.js +++ b/src/core/friendly_errors/param_validator.js @@ -2,12 +2,11 @@ * @for p5 * @requires core */ -import p5 from '../main.js'; import * as constants from '../constants.js'; -import { z } from 'zod'; +import * as z from 'zod'; import dataDoc from '../../../docs/parameterData.json'; -function validateParams(p5, fn) { +function validateParams(p5, fn, lifecycles) { // Cache for Zod schemas let schemaRegistry = new Map(); @@ -19,7 +18,7 @@ function validateParams(p5, fn) { // and so on. const p5Constructors = {}; - fn.loadP5Constructors = function () { + function loadP5Constructors() { // Make a list of all p5 classes to be used for argument validation // This must be done only when everything has loaded otherwise we get // an empty array @@ -447,6 +446,10 @@ function validateParams(p5, fn) { return; // skip FES } + if (!Array.isArray(args)) { + args = Array.from(args); + } + // An edge case: even when all arguments are optional and therefore, // theoretically allowed to stay undefined and valid, it is likely that the // user intended to call the function with non-undefined arguments. Skip @@ -482,11 +485,26 @@ function validateParams(p5, fn) { }; } }; + + lifecycles.presetup = function(){ + loadP5Constructors(); + + const excludes = ['validate']; + for(const f in this){ + if(!excludes.includes(f) && !f.startsWith('_') && typeof this[f] === 'function'){ + const copy = this[f]; + this[f] = (...args) => { + // if (f === 'arc') this.validate(f, args); + this.validate(f, args); + return copy.call(this, ...args); + }; + } + } + }; } export default validateParams; if (typeof p5 !== 'undefined') { validateParams(p5, p5.prototype); - p5.prototype.loadP5Constructors(); -} \ No newline at end of file +} diff --git a/src/core/rendering.js b/src/core/rendering.js index 29a779d7ea..58bd7b5d3f 100644 --- a/src/core/rendering.js +++ b/src/core/rendering.js @@ -126,7 +126,7 @@ function rendering(p5, fn){ * @return {p5.Renderer} */ p5.prototype.createCanvas = function (w, h, renderer, ...args) { - p5._validateParameters('createCanvas', arguments); + // p5._validateParameters('createCanvas', arguments); //optional: renderer, otherwise defaults to p2d let selectedRenderer = constants.P2D @@ -242,7 +242,7 @@ function rendering(p5, fn){ * */ p5.prototype.resizeCanvas = function (w, h, noRedraw) { - p5._validateParameters('resizeCanvas', arguments); + // p5._validateParameters('resizeCanvas', arguments); if (this._renderer) { // Make sure width and height are updated before the renderer resizes so // that framebuffers updated from the resize read the correct size @@ -403,7 +403,7 @@ function rendering(p5, fn){ args[1] = args[0]; args[0] = constants.P2D; } - p5._validateParameters('createGraphics', arguments); + // p5._validateParameters('createGraphics', arguments); return new p5.Graphics(w, h, args[0], this, args[1]); }; diff --git a/src/core/transform.js b/src/core/transform.js index e6e33c47e9..5ba580999c 100644 --- a/src/core/transform.js +++ b/src/core/transform.js @@ -461,7 +461,7 @@ function transform(p5, fn){ * */ fn.rotate = function(angle, axis) { - p5._validateParameters('rotate', arguments); + // p5._validateParameters('rotate', arguments); this._renderer.rotate(this._toRadians(angle), axis); return this; }; @@ -597,7 +597,7 @@ function transform(p5, fn){ */ fn.rotateX = function(angle) { this._assert3d('rotateX'); - p5._validateParameters('rotateX', arguments); + // p5._validateParameters('rotateX', arguments); this._renderer.rotateX(this._toRadians(angle)); return this; }; @@ -733,7 +733,7 @@ function transform(p5, fn){ */ fn.rotateY = function(angle) { this._assert3d('rotateY'); - p5._validateParameters('rotateY', arguments); + // p5._validateParameters('rotateY', arguments); this._renderer.rotateY(this._toRadians(angle)); return this; }; @@ -869,7 +869,7 @@ function transform(p5, fn){ */ fn.rotateZ = function(angle) { this._assert3d('rotateZ'); - p5._validateParameters('rotateZ', arguments); + // p5._validateParameters('rotateZ', arguments); this._renderer.rotateZ(this._toRadians(angle)); return this; }; @@ -1041,7 +1041,7 @@ function transform(p5, fn){ * @chainable */ fn.scale = function(x, y, z) { - p5._validateParameters('scale', arguments); + // p5._validateParameters('scale', arguments); // Only check for Vector argument type if Vector is available if (x instanceof p5.Vector) { const v = x; @@ -1136,7 +1136,7 @@ function transform(p5, fn){ * */ fn.shearX = function(angle) { - p5._validateParameters('shearX', arguments); + // p5._validateParameters('shearX', arguments); const rad = this._toRadians(angle); this._renderer.applyMatrix(1, 0, Math.tan(rad), 1, 0, 0); return this; @@ -1213,7 +1213,7 @@ function transform(p5, fn){ * */ fn.shearY = function(angle) { - p5._validateParameters('shearY', arguments); + // p5._validateParameters('shearY', arguments); const rad = this._toRadians(angle); this._renderer.applyMatrix(1, Math.tan(rad), 0, 1, 0, 0); return this; @@ -1396,7 +1396,7 @@ function transform(p5, fn){ * @chainable */ fn.translate = function(x, y, z) { - p5._validateParameters('translate', arguments); + // p5._validateParameters('translate', arguments); if (this._renderer.isP3D) { this._renderer.translate(x, y, z); } else { diff --git a/src/data/p5.TypedDict.js b/src/data/p5.TypedDict.js index d816769c0c..51fcda7d5b 100644 --- a/src/data/p5.TypedDict.js +++ b/src/data/p5.TypedDict.js @@ -40,7 +40,7 @@ function typedDict(p5, fn){ */ fn.createStringDict = function (key, value) { - p5._validateParameters('createStringDict', arguments); + // p5._validateParameters('createStringDict', arguments); return new p5.StringDict(key, value); }; @@ -74,7 +74,7 @@ function typedDict(p5, fn){ */ fn.createNumberDict = function (key, value) { - p5._validateParameters('createNumberDict', arguments); + // p5._validateParameters('createNumberDict', arguments); return new p5.NumberDict(key, value); }; diff --git a/src/dom/dom.js b/src/dom/dom.js index 50713d327b..ae40b40ace 100644 --- a/src/dom/dom.js +++ b/src/dom/dom.js @@ -99,7 +99,7 @@ function dom(p5, fn){ * */ fn.select = function (e, p) { - p5._validateParameters('select', arguments); + // p5._validateParameters('select', arguments); const container = this._getContainer(p); const res = container.querySelector(e); if (res) { @@ -193,7 +193,7 @@ function dom(p5, fn){ * */ fn.selectAll = function (e, p) { - p5._validateParameters('selectAll', arguments); + // p5._validateParameters('selectAll', arguments); const arr = []; const container = this._getContainer(p); const res = container.querySelectorAll(e); @@ -306,7 +306,7 @@ function dom(p5, fn){ * */ fn.createElement = function (tag, content) { - p5._validateParameters('createElement', arguments); + // p5._validateParameters('createElement', arguments); const elt = document.createElement(tag); if (typeof content !== 'undefined') { elt.innerHTML = content; @@ -381,7 +381,7 @@ function dom(p5, fn){ * */ fn.removeElements = function (e) { - p5._validateParameters('removeElements', arguments); + // p5._validateParameters('removeElements', arguments); // el.remove splices from this._elements, so don't mix iteration with it const isNotCanvasElement = el => !(el.elt instanceof HTMLCanvasElement); const removeableElements = this._elements.filter(isNotCanvasElement); @@ -613,7 +613,7 @@ function dom(p5, fn){ * @return {p5.Element} new p5.Element object. */ fn.createImg = function () { - p5._validateParameters('createImg', arguments); + // p5._validateParameters('createImg', arguments); const elt = document.createElement('img'); const args = arguments; let self; @@ -689,7 +689,7 @@ function dom(p5, fn){ * */ fn.createA = function (href, html, target) { - p5._validateParameters('createA', arguments); + // p5._validateParameters('createA', arguments); const elt = document.createElement('a'); elt.href = href; elt.innerHTML = html; @@ -819,7 +819,7 @@ function dom(p5, fn){ * */ fn.createSlider = function (min, max, value, step) { - p5._validateParameters('createSlider', arguments); + // p5._validateParameters('createSlider', arguments); const elt = document.createElement('input'); elt.type = 'range'; elt.min = min; @@ -910,7 +910,7 @@ function dom(p5, fn){ * */ fn.createButton = function (label, value) { - p5._validateParameters('createButton', arguments); + // p5._validateParameters('createButton', arguments); const elt = document.createElement('button'); elt.innerHTML = label; if (value) elt.value = value; @@ -1014,7 +1014,7 @@ function dom(p5, fn){ * */ fn.createCheckbox = function (...args) { - p5._validateParameters('createCheckbox', args); + // p5._validateParameters('createCheckbox', args); // Create a container element const elt = document.createElement('div'); @@ -1241,7 +1241,7 @@ function dom(p5, fn){ */ fn.createSelect = function (...args) { - p5._validateParameters('createSelect', args); + // p5._validateParameters('createSelect', args); let self; let arg = args[0]; if (arg instanceof Element && arg.elt instanceof HTMLSelectElement) { @@ -1715,7 +1715,7 @@ function dom(p5, fn){ * */ fn.createColorPicker = function (value) { - p5._validateParameters('createColorPicker', arguments); + // p5._validateParameters('createColorPicker', arguments); // TODO: This implementation needs to be rechecked or reimplemented // The way it worked with color is a bit too complex const elt = document.createElement('input'); @@ -1826,7 +1826,7 @@ function dom(p5, fn){ * @return {p5.Element} */ fn.createInput = function (value = '', type = 'text') { - p5._validateParameters('createInput', arguments); + // p5._validateParameters('createInput', arguments); let elt = document.createElement('input'); elt.setAttribute('value', value); elt.setAttribute('type', type); @@ -1936,7 +1936,7 @@ function dom(p5, fn){ * */ fn.createFileInput = function (callback, multiple = false) { - p5._validateParameters('createFileInput', arguments); + // p5._validateParameters('createFileInput', arguments); const handleFileSelect = function (event) { for (const file of event.target.files) { diff --git a/src/dom/p5.MediaElement.js b/src/dom/p5.MediaElement.js index d263617046..fa68e50cee 100644 --- a/src/dom/p5.MediaElement.js +++ b/src/dom/p5.MediaElement.js @@ -1459,7 +1459,7 @@ function media(p5, fn){ * */ fn.createVideo = function (src, callback) { - p5._validateParameters('createVideo', arguments); + // p5._validateParameters('createVideo', arguments); return createMedia(this, 'video', src, callback); }; @@ -1507,7 +1507,7 @@ function media(p5, fn){ * */ fn.createAudio = function (src, callback) { - p5._validateParameters('createAudio', arguments); + // p5._validateParameters('createAudio', arguments); return createMedia(this, 'audio', src, callback); }; @@ -1668,7 +1668,7 @@ function media(p5, fn){ * */ fn.createCapture = function (...args) { - p5._validateParameters('createCapture', args); + // p5._validateParameters('createCapture', args); // return if getUserMedia is not supported by the browser if (!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia)) { diff --git a/src/events/acceleration.js b/src/events/acceleration.js index 8a6d1b86b5..37e657dc12 100644 --- a/src/events/acceleration.js +++ b/src/events/acceleration.js @@ -451,7 +451,7 @@ function acceleration(p5, fn){ */ fn.setMoveThreshold = function (val) { - p5._validateParameters('setMoveThreshold', arguments); + // p5._validateParameters('setMoveThreshold', arguments); move_threshold = val; }; @@ -493,7 +493,7 @@ function acceleration(p5, fn){ */ fn.setShakeThreshold = function (val) { - p5._validateParameters('setShakeThreshold', arguments); + // p5._validateParameters('setShakeThreshold', arguments); shake_threshold = val; }; diff --git a/src/events/keyboard.js b/src/events/keyboard.js index fbc03ffad4..5b0de949ed 100644 --- a/src/events/keyboard.js +++ b/src/events/keyboard.js @@ -903,7 +903,7 @@ function keyboard(p5, fn){ * */ fn.keyIsDown = function(code) { - p5._validateParameters('keyIsDown', arguments); + // p5._validateParameters('keyIsDown', arguments); return this._downKeys[code] || false; }; diff --git a/src/image/image.js b/src/image/image.js index 7db4af9ab4..af08c052dc 100644 --- a/src/image/image.js +++ b/src/image/image.js @@ -148,7 +148,7 @@ function image(p5, fn){ * */ fn.createImage = function(width, height) { - p5._validateParameters('createImage', arguments); + // p5._validateParameters('createImage', arguments); return new p5.Image(width, height); }; @@ -272,7 +272,7 @@ function image(p5, fn){ * @param {String} [extension] */ fn.saveCanvas = function(...args) { - p5._validateParameters('saveCanvas', args); + // p5._validateParameters('saveCanvas', args); // copy arguments to array let htmlCanvas, filename, extension, temporaryGraphics; @@ -658,7 +658,7 @@ function image(p5, fn){ * */ fn.saveFrames = function(fName, ext, _duration, _fps, callback) { - p5._validateParameters('saveFrames', arguments); + // p5._validateParameters('saveFrames', arguments); let duration = _duration || 3; duration = Math.max(Math.min(duration, 15), 0); duration = duration * 1000; diff --git a/src/image/loading_displaying.js b/src/image/loading_displaying.js index b8fa13db81..a95efdcf0c 100644 --- a/src/image/loading_displaying.js +++ b/src/image/loading_displaying.js @@ -107,7 +107,7 @@ function loadingDisplaying(p5, fn){ successCallback, failureCallback ) { - p5._validateParameters('loadImage', arguments); + // p5._validateParameters('loadImage', arguments); try{ let pImg = new p5.Image(1, 1, this); @@ -1063,7 +1063,7 @@ function loadingDisplaying(p5, fn){ ) { // set defaults per spec: https://goo.gl/3ykfOq - p5._validateParameters('image', arguments); + // p5._validateParameters('image', arguments); let defW = img.width; let defH = img.height; @@ -1291,7 +1291,7 @@ function loadingDisplaying(p5, fn){ * @param {p5.Color} color the tint color */ fn.tint = function(...args) { - p5._validateParameters('tint', args); + // p5._validateParameters('tint', args); const c = this.color(...args); this._renderer.states.tint = c._getRGBA([255, 255, 255, 255]); }; @@ -1445,7 +1445,7 @@ function loadingDisplaying(p5, fn){ * */ fn.imageMode = function(m) { - p5._validateParameters('imageMode', arguments); + // p5._validateParameters('imageMode', arguments); if ( m === constants.CORNER || m === constants.CORNERS || diff --git a/src/image/pixels.js b/src/image/pixels.js index c2e2e10c6b..770cfede47 100644 --- a/src/image/pixels.js +++ b/src/image/pixels.js @@ -275,7 +275,7 @@ function pixels(p5, fn){ * @param {(BLEND|DARKEST|LIGHTEST|DIFFERENCE|MULTIPLY|EXCLUSION|SCREEN|REPLACE|OVERLAY|HARD_LIGHT|SOFT_LIGHT|DODGE|BURN|ADD|NORMAL)} blendMode */ fn.blend = function(...args) { - p5._validateParameters('blend', args); + // p5._validateParameters('blend', args); if (this._renderer) { this._renderer.blend(...args); } else { @@ -352,7 +352,7 @@ function pixels(p5, fn){ * @param {Integer} dh */ fn.copy = function(...args) { - p5._validateParameters('copy', args); + // p5._validateParameters('copy', args); let srcImage, sx, sy, sw, sh, dx, dy, dw, dh; if (args.length === 9) { @@ -721,7 +721,7 @@ function pixels(p5, fn){ * frag shader using a `tex0` uniform. */ fn.filter = function(...args) { - p5._validateParameters('filter', args); + // p5._validateParameters('filter', args); let { shader, operation, value, useWebGL } = parseFilterArgs(...args); @@ -916,7 +916,7 @@ function pixels(p5, fn){ * @return {Number[]} color of the pixel at (x, y) in array format `[R, G, B, A]`. */ fn.get = function(x, y, w, h) { - p5._validateParameters('get', arguments); + // p5._validateParameters('get', arguments); return this._renderer.get(...arguments); }; @@ -967,7 +967,7 @@ function pixels(p5, fn){ * */ fn.loadPixels = function(...args) { - p5._validateParameters('loadPixels', args); + // p5._validateParameters('loadPixels', args); this._renderer.loadPixels(); }; @@ -1147,7 +1147,7 @@ function pixels(p5, fn){ * */ fn.updatePixels = function(x, y, w, h) { - p5._validateParameters('updatePixels', arguments); + // p5._validateParameters('updatePixels', arguments); // graceful fail - if loadPixels() or set() has not been called, pixel // array will be empty, ignore call to updatePixels() if (this.pixels.length === 0) { diff --git a/src/io/files.js b/src/io/files.js index 3834dbf6bc..a73a169daf 100644 --- a/src/io/files.js +++ b/src/io/files.js @@ -291,7 +291,7 @@ function files(p5, fn){ * */ fn.loadJSON = async function (path, successCallback, errorCallback) { - p5._validateParameters('loadJSON', arguments); + // p5._validateParameters('loadJSON', arguments); try{ const { data } = await request(path, 'json'); @@ -438,7 +438,7 @@ function files(p5, fn){ * */ fn.loadStrings = async function (path, successCallback, errorCallback) { - p5._validateParameters('loadStrings', arguments); + // p5._validateParameters('loadStrings', arguments); try{ let { data } = await request(path, 'text'); @@ -853,7 +853,7 @@ function files(p5, fn){ * @return {Promise} */ fn.httpGet = async function (path, datatype='text', successCallback, errorCallback) { - p5._validateParameters('httpGet', arguments); + // p5._validateParameters('httpGet', arguments); if (typeof datatype === 'function') { errorCallback = successCallback; @@ -950,7 +950,7 @@ function files(p5, fn){ * @return {Promise} */ fn.httpPost = async function (path, data, datatype='text', successCallback, errorCallback) { - p5._validateParameters('httpPost', arguments); + // p5._validateParameters('httpPost', arguments); // This behave similarly to httpGet and additional options should be passed // as a `Request`` to path. Both method and body will be overridden. @@ -1812,7 +1812,7 @@ function files(p5, fn){ * */ fn.saveJSON = function (json, filename, optimize) { - p5._validateParameters('saveJSON', arguments); + // p5._validateParameters('saveJSON', arguments); let stringify; if (optimize) { stringify = JSON.stringify(json); @@ -1956,7 +1956,7 @@ function files(p5, fn){ * */ fn.saveStrings = function (list, filename, extension, isCRLF) { - p5._validateParameters('saveStrings', arguments); + // p5._validateParameters('saveStrings', arguments); const ext = extension || 'txt'; const pWriter = new p5.PrintWriter(filename, ext); for (let item of list) { @@ -2018,7 +2018,7 @@ function files(p5, fn){ * */ fn.saveTable = function (table, filename, options) { - p5._validateParameters('saveTable', arguments); + // p5._validateParameters('saveTable', arguments); let ext; if (options === undefined) { ext = filename.substring(filename.lastIndexOf('.') + 1, filename.length); diff --git a/src/math/calculation.js b/src/math/calculation.js index 56bc535d74..5075b8c8ad 100644 --- a/src/math/calculation.js +++ b/src/math/calculation.js @@ -147,7 +147,7 @@ function calculation(p5, fn){ * */ fn.constrain = function(n, low, high) { - p5._validateParameters('constrain', arguments); + // p5._validateParameters('constrain', arguments); return Math.max(Math.min(n, high), low); }; @@ -216,7 +216,7 @@ function calculation(p5, fn){ * @return {Number} distance between the two points. */ fn.dist = function(...args) { - p5._validateParameters('dist', args); + // p5._validateParameters('dist', args); if (args.length === 4) { //2D return Math.hypot(args[2] - args[0], args[3] - args[1]); @@ -417,7 +417,7 @@ function calculation(p5, fn){ * */ fn.lerp = function(start, stop, amt) { - p5._validateParameters('lerp', arguments); + // p5._validateParameters('lerp', arguments); return amt * (stop - start) + start; }; @@ -528,7 +528,7 @@ function calculation(p5, fn){ * */ fn.mag = function(x, y) { - p5._validateParameters('mag', arguments); + // p5._validateParameters('mag', arguments); return Math.hypot(x, y); }; @@ -604,7 +604,7 @@ function calculation(p5, fn){ * */ fn.map = function(n, start1, stop1, start2, stop2, withinBounds) { - p5._validateParameters('map', arguments); + // p5._validateParameters('map', arguments); const newval = (n - start1) / (stop1 - start1) * (stop2 - start2) + start2; if (!withinBounds) { return newval; @@ -821,7 +821,7 @@ function calculation(p5, fn){ * */ fn.norm = function(n, start, stop) { - p5._validateParameters('norm', arguments); + // p5._validateParameters('norm', arguments); return this.map(n, start, stop, 0, 1); }; @@ -1094,7 +1094,7 @@ function calculation(p5, fn){ * */ fn.fract = function(toConvert) { - p5._validateParameters('fract', arguments); + // p5._validateParameters('fract', arguments); let sign = 0; let num = Number(toConvert); if (isNaN(num) || Math.abs(num) === Infinity) { diff --git a/src/math/random.js b/src/math/random.js index dca10fad7a..7e272c7e02 100644 --- a/src/math/random.js +++ b/src/math/random.js @@ -261,7 +261,7 @@ function random(p5, fn){ * @return {*} random element from the array. */ fn.random = function(min, max) { - p5._validateParameters('random', arguments); + // p5._validateParameters('random', arguments); let rand; if (this[randomStateProp] != null) { diff --git a/src/math/trigonometry.js b/src/math/trigonometry.js index 8fe2f5f169..89335ca771 100644 --- a/src/math/trigonometry.js +++ b/src/math/trigonometry.js @@ -741,7 +741,7 @@ function trigonometry(p5, fn){ * @return {(RADIANS|DEGREES)} mode either RADIANS or DEGREES */ fn.angleMode = function(mode) { - p5._validateParameters('angleMode', arguments); + // p5._validateParameters('angleMode', arguments); if (typeof mode === 'undefined') { return this._angleMode; } else if (mode === DEGREES || mode === RADIANS) { diff --git a/src/shape/2d_primitives.js b/src/shape/2d_primitives.js index 3f1e0a3506..a060ef07bd 100644 --- a/src/shape/2d_primitives.js +++ b/src/shape/2d_primitives.js @@ -309,7 +309,8 @@ function primitives(p5, fn){ * */ fn.arc = function(x, y, w, h, start, stop, mode, detail) { - p5._validateParameters('arc', arguments); + // this.validate("p5.arc", arguments); + // p5._validateParameters('arc', arguments); // if the current stroke and fill settings wouldn't result in something // visible, exit immediately @@ -480,7 +481,7 @@ function primitives(p5, fn){ * draw a stroke for a detail of more than 50. */ fn.ellipse = function(x, y, w, h, detailX) { - p5._validateParameters('ellipse', arguments); + // p5._validateParameters('ellipse', arguments); return this._renderEllipse(...arguments); }; @@ -530,7 +531,7 @@ function primitives(p5, fn){ * */ fn.circle = function(...args) { - p5._validateParameters('circle', args); + // p5._validateParameters('circle', args); const argss = args.slice( 0, 2); argss.push(args[2], args[2]); return this._renderEllipse(...argss); @@ -710,7 +711,7 @@ function primitives(p5, fn){ * @chainable */ fn.line = function(...args) { - p5._validateParameters('line', args); + // p5._validateParameters('line', args); if (this._renderer.states.strokeColor) { this._renderer.line(...args); @@ -894,7 +895,7 @@ function primitives(p5, fn){ * @chainable */ fn.point = function(...args) { - p5._validateParameters('point', args); + // p5._validateParameters('point', args); if (this._renderer.states.strokeColor) { if (args.length === 1 && args[0] instanceof p5.Vector) { @@ -1055,7 +1056,7 @@ function primitives(p5, fn){ * @chainable */ fn.quad = function(...args) { - p5._validateParameters('quad', args); + // p5._validateParameters('quad', args); if (this._renderer.states.strokeColor || this._renderer.states.fillColor) { if (this._renderer.isP3D && args.length < 12) { @@ -1213,7 +1214,7 @@ function primitives(p5, fn){ * @chainable */ fn.rect = function(...args) { - p5._validateParameters('rect', args); + // p5._validateParameters('rect', args); return this._renderRect(...args); }; @@ -1327,7 +1328,7 @@ function primitives(p5, fn){ * */ fn.square = function(x, y, s, tl, tr, br, bl) { - p5._validateParameters('square', arguments); + // p5._validateParameters('square', arguments); // duplicate width for height in case of square return this._renderRect.call(this, x, y, s, s, tl, tr, br, bl); }; @@ -1431,7 +1432,7 @@ function primitives(p5, fn){ * */ fn.triangle = function(...args) { - p5._validateParameters('triangle', args); + // p5._validateParameters('triangle', args); if (this._renderer.states.strokeColor || this._renderer.states.fillColor) { this._renderer.triangle(args); diff --git a/src/shape/attributes.js b/src/shape/attributes.js index bf787d1df7..10e6f720cd 100644 --- a/src/shape/attributes.js +++ b/src/shape/attributes.js @@ -85,7 +85,7 @@ function attributes(p5, fn){ * */ fn.ellipseMode = function(m) { - p5._validateParameters('ellipseMode', arguments); + // p5._validateParameters('ellipseMode', arguments); if ( m === constants.CORNER || m === constants.CORNERS || @@ -288,7 +288,7 @@ function attributes(p5, fn){ * */ fn.rectMode = function(m) { - p5._validateParameters('rectMode', arguments); + // p5._validateParameters('rectMode', arguments); if ( m === constants.CORNER || m === constants.CORNERS || @@ -427,7 +427,7 @@ function attributes(p5, fn){ * */ fn.strokeCap = function(cap) { - p5._validateParameters('strokeCap', arguments); + // p5._validateParameters('strokeCap', arguments); if ( cap === constants.ROUND || cap === constants.SQUARE || @@ -526,7 +526,7 @@ function attributes(p5, fn){ * */ fn.strokeJoin = function(join) { - p5._validateParameters('strokeJoin', arguments); + // p5._validateParameters('strokeJoin', arguments); if ( join === constants.ROUND || join === constants.BEVEL || @@ -593,7 +593,7 @@ function attributes(p5, fn){ * */ fn.strokeWeight = function(w) { - p5._validateParameters('strokeWeight', arguments); + // p5._validateParameters('strokeWeight', arguments); this._renderer.strokeWeight(w); return this; }; diff --git a/src/shape/curves.js b/src/shape/curves.js index 30f7287d9d..93a19c1d38 100644 --- a/src/shape/curves.js +++ b/src/shape/curves.js @@ -201,7 +201,7 @@ function curves(p5, fn){ * @chainable */ fn.bezier = function(...args) { - p5._validateParameters('bezier', args); + // p5._validateParameters('bezier', args); // if the current stroke and fill settings wouldn't result in something // visible, exit immediately @@ -312,7 +312,7 @@ function curves(p5, fn){ * */ fn.bezierDetail = function(d) { - p5._validateParameters('bezierDetail', arguments); + // p5._validateParameters('bezierDetail', arguments); this._bezierDetail = d; return this; }; @@ -432,7 +432,7 @@ function curves(p5, fn){ * */ fn.bezierPoint = function(a, b, c, d, t) { - p5._validateParameters('bezierPoint', arguments); + // p5._validateParameters('bezierPoint', arguments); const adjustedT = 1 - t; return ( @@ -550,7 +550,7 @@ function curves(p5, fn){ * */ fn.bezierTangent = function(a, b, c, d, t) { - p5._validateParameters('bezierTangent', arguments); + // p5._validateParameters('bezierTangent', arguments); const adjustedT = 1 - t; return ( @@ -756,7 +756,7 @@ function curves(p5, fn){ * @chainable */ fn.curve = function(...args) { - p5._validateParameters('curve', args); + // p5._validateParameters('curve', args); if (this._renderer.states.strokeColor) { this._renderer.curve(...args); @@ -815,7 +815,7 @@ function curves(p5, fn){ * */ fn.curveTightness = function(t) { - p5._validateParameters('curveTightness', arguments); + // p5._validateParameters('curveTightness', arguments); this._renderer._curveTightness = t; return this; }; @@ -933,7 +933,7 @@ function curves(p5, fn){ * */ fn.curvePoint = function(a, b, c, d, t) { - p5._validateParameters('curvePoint', arguments); + // p5._validateParameters('curvePoint', arguments); const s = this._renderer._curveTightness, t3 = t * t * t, t2 = t * t, @@ -1049,7 +1049,7 @@ function curves(p5, fn){ * */ fn.curveTangent = function(a, b, c, d, t) { - p5._validateParameters('curveTangent', arguments); + // p5._validateParameters('curveTangent', arguments); const s = this._renderer._curveTightness, tt3 = t * t * 3, diff --git a/src/shape/vertex.js b/src/shape/vertex.js index 34f452f45f..6252d0677a 100644 --- a/src/shape/vertex.js +++ b/src/shape/vertex.js @@ -398,7 +398,7 @@ function vertex(p5, fn){ * */ fn.beginShape = function(kind) { - p5._validateParameters('beginShape', arguments); + // p5._validateParameters('beginShape', arguments); this._renderer.beginShape(...arguments); }; @@ -1061,7 +1061,7 @@ function vertex(p5, fn){ * */ fn.curveVertex = function(...args) { - p5._validateParameters('curveVertex', args); + // p5._validateParameters('curveVertex', args); this._renderer.splineVertex(...args); return this; }; @@ -1230,7 +1230,7 @@ function vertex(p5, fn){ * */ fn.endShape = function(mode, count = 1) { - p5._validateParameters('endShape', arguments); + // p5._validateParameters('endShape', arguments); if (count < 1) { console.log('🌸 p5.js says: You can not have less than one instance'); count = 1; @@ -1487,7 +1487,7 @@ function vertex(p5, fn){ } else { [x1, y1, z1, x2, y2, z2] = args; } - p5._validateParameters('quadraticVertex', args); + // p5._validateParameters('quadraticVertex', args); const prevOrder = this.bezierOrder(); this.bezierOrder(2); this.bezierVertex(x1, y1, z1); @@ -1680,7 +1680,7 @@ function vertex(p5, fn){ */ fn.normal = function(x, y, z) { this._assert3d('normal'); - p5._validateParameters('normal', arguments); + // p5._validateParameters('normal', arguments); this._renderer.normal(...arguments); return this; @@ -1854,7 +1854,7 @@ function vertex(p5, fn){ */ fn.vertexProperty = function(attributeName, data){ // this._assert3d('vertexProperty'); - // p5._validateParameters('vertexProperty', arguments); + p5._validateParameters('vertexProperty', arguments); this._renderer.vertexProperty(attributeName, data); }; } diff --git a/src/utilities/string_functions.js b/src/utilities/string_functions.js index 07bb5dc073..94e4cfdf9f 100644 --- a/src/utilities/string_functions.js +++ b/src/utilities/string_functions.js @@ -47,7 +47,7 @@ function stringFunctions(p5, fn){ * */ fn.join = function(list, separator) { - p5._validateParameters('join', arguments); + // p5._validateParameters('join', arguments); return list.join(separator); }; @@ -106,7 +106,7 @@ function stringFunctions(p5, fn){ * */ fn.match = function(str, reg) { - p5._validateParameters('match', arguments); + // p5._validateParameters('match', arguments); return str.match(reg); }; @@ -176,7 +176,7 @@ function stringFunctions(p5, fn){ * */ fn.matchAll = function(str, reg) { - p5._validateParameters('matchAll', arguments); + // p5._validateParameters('matchAll', arguments); const re = new RegExp(reg, 'g'); let match = re.exec(str); const matches = []; @@ -269,7 +269,7 @@ function stringFunctions(p5, fn){ * @return {String[]} formatted strings. */ fn.nf = function(nums, left, right) { - p5._validateParameters('nf', arguments); + // p5._validateParameters('nf', arguments); if (nums instanceof Array) { return nums.map(x => doNf(x, left, right)); } else { @@ -402,7 +402,7 @@ function stringFunctions(p5, fn){ * @return {String[]} formatted strings. */ fn.nfc = function(num, right) { - p5._validateParameters('nfc', arguments); + // p5._validateParameters('nfc', arguments); if (num instanceof Array) { return num.map(x => doNfc(x, right)); } else { @@ -544,7 +544,7 @@ function stringFunctions(p5, fn){ * @return {String[]} formatted strings. */ fn.nfp = function(...args) { - p5._validateParameters('nfp', args); + // p5._validateParameters('nfp', args); const nfRes = fn.nf.apply(this, args); if (nfRes instanceof Array) { return nfRes.map(addNfp); @@ -661,7 +661,7 @@ function stringFunctions(p5, fn){ * @return {String[]} formatted strings. */ fn.nfs = function(...args) { - p5._validateParameters('nfs', args); + // p5._validateParameters('nfs', args); const nfRes = fn.nf.apply(this, args); if (nfRes instanceof Array) { return nfRes.map(addNfs); @@ -731,7 +731,7 @@ function stringFunctions(p5, fn){ * */ fn.split = function(str, delim) { - p5._validateParameters('split', arguments); + // p5._validateParameters('split', arguments); return str.split(delim); }; @@ -874,7 +874,7 @@ function stringFunctions(p5, fn){ * */ fn.splitTokens = function(value, delims) { - p5._validateParameters('splitTokens', arguments); + // p5._validateParameters('splitTokens', arguments); let d; if (typeof delims !== 'undefined') { let str = delims; @@ -974,7 +974,7 @@ function stringFunctions(p5, fn){ * @return {String[]} trimmed strings. */ fn.trim = function(str) { - p5._validateParameters('trim', arguments); + // p5._validateParameters('trim', arguments); if (str instanceof Array) { return str.map(this.trim); } else { diff --git a/src/webgl/3d_primitives.js b/src/webgl/3d_primitives.js index a2af7f3476..1c880d87d0 100644 --- a/src/webgl/3d_primitives.js +++ b/src/webgl/3d_primitives.js @@ -554,7 +554,7 @@ function primitives3D(p5, fn){ detailY = 1 ) { this._assert3d('plane'); - p5._validateParameters('plane', arguments); + // p5._validateParameters('plane', arguments); this._renderer.plane(width, height, detailX, detailY); return this; @@ -691,7 +691,7 @@ function primitives3D(p5, fn){ */ fn.box = function(width, height, depth, detailX, detailY) { this._assert3d('box'); - p5._validateParameters('box', arguments); + // p5._validateParameters('box', arguments); this._renderer.box(width, height, depth, detailX, detailY); @@ -823,7 +823,7 @@ function primitives3D(p5, fn){ */ fn.sphere = function(radius = 50, detailX = 24, detailY = 16) { this._assert3d('sphere'); - p5._validateParameters('sphere', arguments); + // p5._validateParameters('sphere', arguments); this._renderer.sphere(radius, detailX, detailY); @@ -1051,7 +1051,7 @@ function primitives3D(p5, fn){ topCap = true ) { this._assert3d('cylinder'); - p5._validateParameters('cylinder', arguments); + // p5._validateParameters('cylinder', arguments); this._renderer.cylinder(radius, height, detailX, detailY, bottomCap, topCap); @@ -1271,7 +1271,7 @@ function primitives3D(p5, fn){ cap = true ) { this._assert3d('cone'); - p5._validateParameters('cone', arguments); + // p5._validateParameters('cone', arguments); this._renderer.cone(radius, height, detailX, detailY, cap); @@ -1454,7 +1454,7 @@ function primitives3D(p5, fn){ detailY = 16 ) { this._assert3d('ellipsoid'); - p5._validateParameters('ellipsoid', arguments); + // p5._validateParameters('ellipsoid', arguments); this._renderer.ellipsoid(radiusX, radiusY, radiusZ, detailX, detailY); @@ -1613,7 +1613,7 @@ function primitives3D(p5, fn){ */ fn.torus = function(radius, tubeRadius, detailX, detailY) { this._assert3d('torus'); - p5._validateParameters('torus', arguments); + // p5._validateParameters('torus', arguments); this._renderer.torus(radius, tubeRadius, detailX, detailY); diff --git a/src/webgl/interaction.js b/src/webgl/interaction.js index 71f6cf8c62..1b257ce6fd 100644 --- a/src/webgl/interaction.js +++ b/src/webgl/interaction.js @@ -169,7 +169,7 @@ function interaction(p5, fn){ options ) { this._assert3d('orbitControl'); - p5._validateParameters('orbitControl', arguments); + // p5._validateParameters('orbitControl', arguments); const cam = this._renderer.states.curCamera; @@ -687,7 +687,7 @@ function interaction(p5, fn){ fn.debugMode = function(...args) { this._assert3d('debugMode'); - p5._validateParameters('debugMode', args); + // p5._validateParameters('debugMode', args); // start by removing existing 'post' registered debug methods for (let i = this._registeredMethods.post.length - 1; i >= 0; i--) { diff --git a/src/webgl/light.js b/src/webgl/light.js index bfeca289e8..2d66d79ad0 100644 --- a/src/webgl/light.js +++ b/src/webgl/light.js @@ -191,7 +191,7 @@ function light(p5, fn){ */ fn.ambientLight = function (v1, v2, v3, a) { this._assert3d('ambientLight'); - p5._validateParameters('ambientLight', arguments); + // p5._validateParameters('ambientLight', arguments); this._renderer.ambientLight(...arguments); @@ -442,7 +442,7 @@ function light(p5, fn){ */ fn.specularColor = function (v1, v2, v3) { this._assert3d('specularColor'); - p5._validateParameters('specularColor', arguments); + // p5._validateParameters('specularColor', arguments); this._renderer.specularColor(...arguments); @@ -629,7 +629,7 @@ function light(p5, fn){ */ fn.directionalLight = function (v1, v2, v3, x, y, z) { this._assert3d('directionalLight'); - p5._validateParameters('directionalLight', arguments); + // p5._validateParameters('directionalLight', arguments); //@TODO: check parameters number this._renderer.directionalLight(...arguments); @@ -872,7 +872,7 @@ function light(p5, fn){ */ fn.pointLight = function (v1, v2, v3, x, y, z) { this._assert3d('pointLight'); - p5._validateParameters('pointLight', arguments); + // p5._validateParameters('pointLight', arguments); //@TODO: check parameters number this._renderer.pointLight(...arguments); @@ -1151,7 +1151,7 @@ function light(p5, fn){ quadraticAttenuation ) { this._assert3d('lightFalloff'); - p5._validateParameters('lightFalloff', arguments); + // p5._validateParameters('lightFalloff', arguments); this._renderer.lightFalloff( constantAttenuation, @@ -1378,7 +1378,7 @@ function light(p5, fn){ concentration ) { this._assert3d('spotLight'); - p5._validateParameters('spotLight', arguments); + // p5._validateParameters('spotLight', arguments); this._renderer.spotLight(...arguments); @@ -1445,7 +1445,7 @@ function light(p5, fn){ */ fn.noLights = function (...args) { this._assert3d('noLights'); - p5._validateParameters('noLights', args); + // p5._validateParameters('noLights', args); this._renderer.noLights(); diff --git a/src/webgl/loading.js b/src/webgl/loading.js index 28c6099432..a2b861c94d 100755 --- a/src/webgl/loading.js +++ b/src/webgl/loading.js @@ -335,7 +335,7 @@ function loading(p5, fn){ * @return {Promise} new p5.Geometry object. */ fn.loadModel = async function (path, fileType, normalize, successCallback, failureCallback) { - p5._validateParameters('loadModel', arguments); + // p5._validateParameters('loadModel', arguments); let flipU = false; let flipV = false; @@ -1098,7 +1098,7 @@ function loading(p5, fn){ */ fn.model = function (model, count = 1) { this._assert3d('model'); - p5._validateParameters('model', arguments); + // p5._validateParameters('model', arguments); if (model.vertices.length > 0) { if (!this._renderer.geometryInHash(model.gid)) { diff --git a/src/webgl/material.js b/src/webgl/material.js index 3fdb3733cd..3dd3068dc1 100644 --- a/src/webgl/material.js +++ b/src/webgl/material.js @@ -125,7 +125,7 @@ function material(p5, fn){ successCallback, failureCallback ) { - p5._validateParameters('loadShader', arguments); + // p5._validateParameters('loadShader', arguments); const loadedShader = new Shader(); @@ -510,7 +510,7 @@ function material(p5, fn){ * */ fn.createShader = function (vertSrc, fragSrc, options) { - p5._validateParameters('createShader', arguments); + // p5._validateParameters('createShader', arguments); return new Shader(this._renderer, vertSrc, fragSrc, options); }; @@ -605,7 +605,7 @@ function material(p5, fn){ * */ fn.createFilterShader = function (fragSrc) { - p5._validateParameters('createFilterShader', arguments); + // p5._validateParameters('createFilterShader', arguments); let defaultVertV1 = ` uniform mat4 uModelViewMatrix; uniform mat4 uProjectionMatrix; @@ -838,7 +838,7 @@ function material(p5, fn){ */ fn.shader = function (s) { this._assert3d('shader'); - p5._validateParameters('shader', arguments); + // p5._validateParameters('shader', arguments); this._renderer.shader(s); @@ -1011,7 +1011,7 @@ function material(p5, fn){ */ fn.strokeShader = function (s) { this._assert3d('strokeShader'); - p5._validateParameters('strokeShader', arguments); + // p5._validateParameters('strokeShader', arguments); this._renderer.strokeShader(s); @@ -1168,7 +1168,7 @@ function material(p5, fn){ */ fn.imageShader = function (s) { this._assert3d('imageShader'); - p5._validateParameters('imageShader', arguments); + // p5._validateParameters('imageShader', arguments); this._renderer.imageShader(s); @@ -2273,7 +2273,7 @@ function material(p5, fn){ */ fn.texture = function (tex) { this._assert3d('texture'); - p5._validateParameters('texture', arguments); + // p5._validateParameters('texture', arguments); // NOTE: make generic or remove need for if (tex.gifProperties) { @@ -2787,7 +2787,7 @@ function material(p5, fn){ */ fn.normalMaterial = function (...args) { this._assert3d('normalMaterial'); - p5._validateParameters('normalMaterial', args); + // p5._validateParameters('normalMaterial', args); this._renderer.normalMaterial(...args); @@ -3014,7 +3014,7 @@ function material(p5, fn){ */ fn.ambientMaterial = function (v1, v2, v3) { this._assert3d('ambientMaterial'); - p5._validateParameters('ambientMaterial', arguments); + // p5._validateParameters('ambientMaterial', arguments); const color = fn.color.apply(this, arguments); this._renderer.states._hasSetAmbient = true; @@ -3110,7 +3110,7 @@ function material(p5, fn){ */ fn.emissiveMaterial = function (v1, v2, v3, a) { this._assert3d('emissiveMaterial'); - p5._validateParameters('emissiveMaterial', arguments); + // p5._validateParameters('emissiveMaterial', arguments); const color = fn.color.apply(this, arguments); this._renderer.states.curEmissiveColor = color._array; @@ -3365,7 +3365,7 @@ function material(p5, fn){ */ fn.specularMaterial = function (v1, v2, v3, alpha) { this._assert3d('specularMaterial'); - p5._validateParameters('specularMaterial', arguments); + // p5._validateParameters('specularMaterial', arguments); const color = fn.color.apply(this, arguments); this._renderer.states.curSpecularColor = color._array; @@ -3438,7 +3438,7 @@ function material(p5, fn){ */ fn.shininess = function (shine) { this._assert3d('shininess'); - p5._validateParameters('shininess', arguments); + // p5._validateParameters('shininess', arguments); this._renderer.shininess(shine); diff --git a/src/webgl/p5.Camera.js b/src/webgl/p5.Camera.js index c85d14f335..f87628b253 100644 --- a/src/webgl/p5.Camera.js +++ b/src/webgl/p5.Camera.js @@ -3182,7 +3182,7 @@ function camera(p5, fn){ */ fn.camera = function (...args) { this._assert3d('camera'); - p5._validateParameters('camera', args); + // p5._validateParameters('camera', args); this._renderer.camera(...args); return this; }; @@ -3313,7 +3313,7 @@ function camera(p5, fn){ */ fn.perspective = function (...args) { this._assert3d('perspective'); - p5._validateParameters('perspective', args); + // p5._validateParameters('perspective', args); this._renderer.perspective(...args); return this; }; @@ -3437,7 +3437,7 @@ function camera(p5, fn){ */ fn.linePerspective = function (enable) { - p5._validateParameters('linePerspective', arguments); + // p5._validateParameters('linePerspective', arguments); if (!(this._renderer instanceof RendererGL)) { throw new Error('linePerspective() must be called in WebGL mode.'); } @@ -3550,7 +3550,7 @@ function camera(p5, fn){ */ fn.ortho = function (...args) { this._assert3d('ortho'); - p5._validateParameters('ortho', args); + // p5._validateParameters('ortho', args); this._renderer.ortho(...args); return this; }; @@ -3662,7 +3662,7 @@ function camera(p5, fn){ */ fn.frustum = function (...args) { this._assert3d('frustum'); - p5._validateParameters('frustum', args); + // p5._validateParameters('frustum', args); this._renderer.frustum(...args); return this; }; From 3c419f4012a392f72d0fe0bb3c4b83a949ddee0d Mon Sep 17 00:00:00 2001 From: limzykenneth Date: Wed, 18 Dec 2024 19:45:11 +0000 Subject: [PATCH 2/7] Refactor FES to not use side effect import --- src/app.js | 8 +- src/core/friendly_errors/fes_core.js | 1991 ++++++++++++----------- src/core/friendly_errors/file_errors.js | 12 +- src/core/friendly_errors/index.js | 8 +- src/core/friendly_errors/stacktrace.js | 17 +- 5 files changed, 1027 insertions(+), 1009 deletions(-) diff --git a/src/app.js b/src/app.js index c725ad5331..27a98bcb5e 100644 --- a/src/app.js +++ b/src/app.js @@ -1,10 +1,10 @@ // core import p5 from './core/main'; -import './core/friendly_errors/stacktrace'; +// import './core/friendly_errors/stacktrace'; // import './core/friendly_errors/validate_params'; -import './core/friendly_errors/file_errors'; -import './core/friendly_errors/fes_core'; -import './core/friendly_errors/sketch_reader'; +// import './core/friendly_errors/file_errors'; +// import './core/friendly_errors/fes_core'; +// import './core/friendly_errors/sketch_reader'; import shape from './shape'; shape(p5); diff --git a/src/core/friendly_errors/fes_core.js b/src/core/friendly_errors/fes_core.js index 25df52d5f3..9e6ca11432 100644 --- a/src/core/friendly_errors/fes_core.js +++ b/src/core/friendly_errors/fes_core.js @@ -22,1083 +22,1088 @@ * sequence of each function, please look at the FES Reference + Dev Notes: * https://github.com/processing/p5.js/blob/main/contributor_docs/fes_reference_dev_notes.md */ -import p5 from '../main'; import { translator } from '../internationalization'; import errorTable from './browser_errors'; import * as contants from '../constants'; -// p5.js blue, p5.js orange, auto dark green; fallback p5.js darkened magenta -// See testColors below for all the color codes and names -const typeColors = ['#2D7BB6', '#EE9900', '#4DB200', '#C83C00']; -let misusedAtTopLevelCode = null; -let defineMisusedAtTopLevelCode = null; - -// the threshold for the maximum allowed levenshtein distance -// used in misspelling detection -const EDIT_DIST_THRESHOLD = 2; - -// to enable or disable styling (color, font-size, etc. ) for fes messages -const ENABLE_FES_STYLING = false; - -if (typeof IS_MINIFIED !== 'undefined') { - p5._friendlyError = - p5._checkForUserDefinedFunctions = - p5._fesErrorMonitor = - () => {}; -} else { - let doFriendlyWelcome = false; // TEMP until we get it all working LM - - // const errorTable = require('./browser_errors').default; - - // -- Borrowed from jQuery 1.11.3 -- - const class2type = {}; - const toString = class2type.toString; - const names = [ - 'Boolean', - 'Number', - 'String', - 'Function', - 'Array', - 'Date', - 'RegExp', - 'Object', - 'Error' - ]; - for (let n = 0; n < names.length; n++) { - class2type[`[object ${names[n]}]`] = names[n].toLowerCase(); - } - const getType = obj => { - if (obj == null) { - return `${obj}`; - } - return typeof obj === 'object' || typeof obj === 'function' - ? class2type[toString.call(obj)] || 'object' - : typeof obj; - }; - - // -- End borrow -- - - // entry points into user-defined code - const entryPoints = [ - 'setup', - 'draw', - 'preload', - 'deviceMoved', - 'deviceTurned', - 'deviceShaken', - 'doubleClicked', - 'mousePressed', - 'mouseReleased', - 'mouseMoved', - 'mouseDragged', - 'mouseClicked', - 'mouseWheel', - 'touchStarted', - 'touchMoved', - 'touchEnded', - 'keyPressed', - 'keyReleased', - 'keyTyped', - 'windowResized' - ]; - - const friendlyWelcome = () => { - // p5.js brand - magenta: #ED225D - //const astrixBgColor = 'transparent'; - //const astrixTxtColor = '#ED225D'; - //const welcomeBgColor = '#ED225D'; - //const welcomeTextColor = 'white'; - const welcomeMessage = translator('fes.pre', { - message: translator('fes.welcome') - }); - console.log( - ' _ \n' + - ' /\\| |/\\ \n' + - " \\ ` ' / \n" + - ' / , . \\ \n' + - ' \\/|_|\\/ ' + - '\n\n' + - welcomeMessage - ); - }; - - /** - * Takes a message and a p5 function func, and adds a link pointing to - * the reference documentation of func at the end of the message - * - * @method mapToReference - * @private - * @param {String} message the words to be said - * @param {String} [func] the name of function - * - * @returns {String} - */ - const mapToReference = (message, func) => { - let msgWithReference = ''; - if (func == null || func.substring(0, 4) === 'load') { - msgWithReference = message; - } else { - const methodParts = func.split('.'); - const referenceSection = - methodParts.length > 1 ? `${methodParts[0]}.${methodParts[1]}` : 'p5'; - - const funcName = - methodParts.length === 1 ? func : methodParts.slice(2).join('/'); - - //Whenever func having p5.[Class] is encountered, we need to have the error link as mentioned below else different link - funcName.startsWith('p5.') ? - msgWithReference = `${message} (http://p5js.org/reference/#/${referenceSection}.${funcName})` : - msgWithReference = `${message} (http://p5js.org/reference/#/${referenceSection}/${funcName})`; - } - return msgWithReference; - }; - - /** - * Prints out a fancy, colorful message to the console log - * Attaches Friendly Errors prefix [fes.pre] to the message. - * - * @method _report - * @private - * @param {String} message Message to be printed - * @param {String} [func] Name of function - * @param {Number|String} [color] CSS color code - * - * @return console logs - */ - p5._report = (message, func, color) => { - // if p5._fesLogger is set ( i.e we are running tests ), use that - // instead of console.log - const log = - p5._fesLogger == null ? console.log.bind(console) : p5._fesLogger; - - if (doFriendlyWelcome) { - friendlyWelcome(); - doFriendlyWelcome = false; - } - if ('undefined' === getType(color)) { - color = '#B40033'; // dark magenta - } else if (getType(color) === 'number') { - // Type to color - color = typeColors[color]; +function fesCore(p5, fn){ + // p5.js blue, p5.js orange, auto dark green; fallback p5.js darkened magenta + // See testColors below for all the color codes and names + const typeColors = ['#2D7BB6', '#EE9900', '#4DB200', '#C83C00']; + let misusedAtTopLevelCode = null; + let defineMisusedAtTopLevelCode = null; + + // the threshold for the maximum allowed levenshtein distance + // used in misspelling detection + const EDIT_DIST_THRESHOLD = 2; + + // to enable or disable styling (color, font-size, etc. ) for fes messages + const ENABLE_FES_STYLING = false; + + if (typeof IS_MINIFIED !== 'undefined') { + p5._friendlyError = + p5._checkForUserDefinedFunctions = + p5._fesErrorMonitor = + () => {}; + } else { + let doFriendlyWelcome = false; // TEMP until we get it all working LM + + // const errorTable = require('./browser_errors').default; + + // -- Borrowed from jQuery 1.11.3 -- + const class2type = {}; + const toString = class2type.toString; + const names = [ + 'Boolean', + 'Number', + 'String', + 'Function', + 'Array', + 'Date', + 'RegExp', + 'Object', + 'Error' + ]; + for (let n = 0; n < names.length; n++) { + class2type[`[object ${names[n]}]`] = names[n].toLowerCase(); } + const getType = obj => { + if (obj == null) { + return `${obj}`; + } + return typeof obj === 'object' || typeof obj === 'function' + ? class2type[toString.call(obj)] || 'object' + : typeof obj; + }; + + // -- End borrow -- + + // entry points into user-defined code + const entryPoints = [ + 'setup', + 'draw', + 'preload', + 'deviceMoved', + 'deviceTurned', + 'deviceShaken', + 'doubleClicked', + 'mousePressed', + 'mouseReleased', + 'mouseMoved', + 'mouseDragged', + 'mouseClicked', + 'mouseWheel', + 'touchStarted', + 'touchMoved', + 'touchEnded', + 'keyPressed', + 'keyReleased', + 'keyTyped', + 'windowResized' + ]; + + const friendlyWelcome = () => { + // p5.js brand - magenta: #ED225D + //const astrixBgColor = 'transparent'; + //const astrixTxtColor = '#ED225D'; + //const welcomeBgColor = '#ED225D'; + //const welcomeTextColor = 'white'; + const welcomeMessage = translator('fes.pre', { + message: translator('fes.welcome') + }); + console.log( + ' _ \n' + + ' /\\| |/\\ \n' + + " \\ ` ' / \n" + + ' / , . \\ \n' + + ' \\/|_|\\/ ' + + '\n\n' + + welcomeMessage + ); + }; + + /** + * Takes a message and a p5 function func, and adds a link pointing to + * the reference documentation of func at the end of the message + * + * @method mapToReference + * @private + * @param {String} message the words to be said + * @param {String} [func] the name of function + * + * @returns {String} + */ + const mapToReference = (message, func) => { + let msgWithReference = ''; + if (func == null || func.substring(0, 4) === 'load') { + msgWithReference = message; + } else { + const methodParts = func.split('.'); + const referenceSection = + methodParts.length > 1 ? `${methodParts[0]}.${methodParts[1]}` : 'p5'; - // Add a link to the reference docs of func at the end of the message - message = mapToReference(message, func); - let style = [`color: ${color}`, 'font-family: Arial', 'font-size: larger']; - const prefixedMsg = translator('fes.pre', { message }); - - if (ENABLE_FES_STYLING) { - log('%c' + prefixedMsg, style.join(';')); - } else { - log(prefixedMsg); - } - }; - /** - * This is a generic method that can be called from anywhere in the p5 - * library to alert users to a common error. - * - * @method _friendlyError - * @private - * @param {String} message Message to be printed - * @param {String} [func] Name of the function linked to error - * @param {Number|String} [color] CSS color code - */ - p5._friendlyError = function(message, func, color) { - p5._report(message, func, color); - }; - - /** - * This is called internally if there is an error with autoplay. Generates - * and prints a friendly error message [fes.autoplay]. - * - * @method _friendlyAutoplayError - * @private - */ - p5._friendlyAutoplayError = function(src) { - const message = translator('fes.autoplay', { - src, - url: 'https://developer.mozilla.org/docs/Web/Media/Autoplay_guide' - }); - console.log(translator('fes.pre', { message })); - }; + const funcName = + methodParts.length === 1 ? func : methodParts.slice(2).join('/'); - /** - * Measures dissimilarity between two strings by calculating - * the Levenshtein distance. - * - * If the "distance" between them is small enough, it is - * reasonable to think that one is the misspelled version of the other. - * - * Specifically, this uses the Wagner–Fischer algorithm. - * @method computeEditDistance - * @private - * @param {String} w1 the first word - * @param {String} w2 the second word - * - * @returns {Number} the "distance" between the two words, a smaller value - * indicates that the words are similar - */ - const computeEditDistance = (w1, w2) => { - const l1 = w1.length, - l2 = w2.length; - if (l1 === 0) return w2; - if (l2 === 0) return w1; - - let prev = []; - let cur = []; + //Whenever func having p5.[Class] is encountered, we need to have the error link as mentioned below else different link + funcName.startsWith('p5.') ? + msgWithReference = `${message} (http://p5js.org/reference/#/${referenceSection}.${funcName})` : + msgWithReference = `${message} (http://p5js.org/reference/#/${referenceSection}/${funcName})`; + } + return msgWithReference; + }; + + /** + * Prints out a fancy, colorful message to the console log + * Attaches Friendly Errors prefix [fes.pre] to the message. + * + * @method _report + * @private + * @param {String} message Message to be printed + * @param {String} [func] Name of function + * @param {Number|String} [color] CSS color code + * + * @return console logs + */ + p5._report = (message, func, color) => { + // if p5._fesLogger is set ( i.e we are running tests ), use that + // instead of console.log + const log = + p5._fesLogger == null ? console.log.bind(console) : p5._fesLogger; + + if (doFriendlyWelcome) { + friendlyWelcome(); + doFriendlyWelcome = false; + } + if ('undefined' === getType(color)) { + color = '#B40033'; // dark magenta + } else if (getType(color) === 'number') { + // Type to color + color = typeColors[color]; + } - for (let j = 0; j < l2 + 1; j++) { - cur[j] = j; - } + // Add a link to the reference docs of func at the end of the message + message = mapToReference(message, func); + let style = [`color: ${color}`, 'font-family: Arial', 'font-size: larger']; + const prefixedMsg = translator('fes.pre', { message }); - prev = cur; + if (ENABLE_FES_STYLING) { + log('%c' + prefixedMsg, style.join(';')); + } else { + log(prefixedMsg); + } + }; + /** + * This is a generic method that can be called from anywhere in the p5 + * library to alert users to a common error. + * + * @method _friendlyError + * @private + * @param {String} message Message to be printed + * @param {String} [func] Name of the function linked to error + * @param {Number|String} [color] CSS color code + */ + p5._friendlyError = function(message, func, color) { + p5._report(message, func, color); + }; + + /** + * This is called internally if there is an error with autoplay. Generates + * and prints a friendly error message [fes.autoplay]. + * + * @method _friendlyAutoplayError + * @private + */ + p5._friendlyAutoplayError = function(src) { + const message = translator('fes.autoplay', { + src, + url: 'https://developer.mozilla.org/docs/Web/Media/Autoplay_guide' + }); + console.log(translator('fes.pre', { message })); + }; + + /** + * Measures dissimilarity between two strings by calculating + * the Levenshtein distance. + * + * If the "distance" between them is small enough, it is + * reasonable to think that one is the misspelled version of the other. + * + * Specifically, this uses the Wagner–Fischer algorithm. + * @method computeEditDistance + * @private + * @param {String} w1 the first word + * @param {String} w2 the second word + * + * @returns {Number} the "distance" between the two words, a smaller value + * indicates that the words are similar + */ + const computeEditDistance = (w1, w2) => { + const l1 = w1.length, + l2 = w2.length; + if (l1 === 0) return w2; + if (l2 === 0) return w1; + + let prev = []; + let cur = []; - for (let i = 1; i < l1 + 1; i++) { - cur = []; for (let j = 0; j < l2 + 1; j++) { - if (j === 0) { - cur[j] = i; - } else { - let a1 = w1[i - 1], - a2 = w2[j - 1]; - let temp = 999999; - let cost = a1.toLowerCase() === a2.toLowerCase() ? 0 : 1; - temp = temp > cost + prev[j - 1] ? cost + prev[j - 1] : temp; - temp = temp > 1 + cur[j - 1] ? 1 + cur[j - 1] : temp; - temp = temp > 1 + prev[j] ? 1 + prev[j] : temp; - cur[j] = temp; - } + cur[j] = j; } - prev = cur; - } - return cur[l2]; - }; - - /** - * Checks capitalization for user defined functions. - * - * Generates and prints a friendly error message using key: - * "fes.checkUserDefinedFns". - * - * @method checkForUserDefinedFunctions - * @private - * @param {*} context Current default context. Set to window in - * "global mode" and to a p5 instance in "instance mode" - */ - const checkForUserDefinedFunctions = context => { - if (p5.disableFriendlyErrors) return; - - // if using instance mode, this function would be called with the current - // instance as context - const instanceMode = context instanceof p5; - context = instanceMode ? context : window; - const fnNames = entryPoints; - - const fxns = {}; - // lowercasename -> actualName mapping - fnNames.forEach(symbol => { - fxns[symbol.toLowerCase()] = symbol; - }); + prev = cur; - for (const prop of Object.keys(context)) { - const lowercase = prop.toLowerCase(); + for (let i = 1; i < l1 + 1; i++) { + cur = []; + for (let j = 0; j < l2 + 1; j++) { + if (j === 0) { + cur[j] = i; + } else { + let a1 = w1[i - 1], + a2 = w2[j - 1]; + let temp = 999999; + let cost = a1.toLowerCase() === a2.toLowerCase() ? 0 : 1; + temp = temp > cost + prev[j - 1] ? cost + prev[j - 1] : temp; + temp = temp > 1 + cur[j - 1] ? 1 + cur[j - 1] : temp; + temp = temp > 1 + prev[j] ? 1 + prev[j] : temp; + cur[j] = temp; + } + } + prev = cur; + } - // check if the lowercase property name has an entry in fxns, if the - // actual name with correct capitalization doesnt exist in context, - // and if the user-defined symbol is of the type function - if ( - fxns[lowercase] && - !context[fxns[lowercase]] && - typeof context[prop] === 'function' - ) { - const msg = translator('fes.checkUserDefinedFns', { - name: prop, - actualName: fxns[lowercase] - }); + return cur[l2]; + }; + + /** + * Checks capitalization for user defined functions. + * + * Generates and prints a friendly error message using key: + * "fes.checkUserDefinedFns". + * + * @method checkForUserDefinedFunctions + * @private + * @param {*} context Current default context. Set to window in + * "global mode" and to a p5 instance in "instance mode" + */ + const checkForUserDefinedFunctions = context => { + if (p5.disableFriendlyErrors) return; + + // if using instance mode, this function would be called with the current + // instance as context + const instanceMode = context instanceof p5; + context = instanceMode ? context : window; + const fnNames = entryPoints; + + const fxns = {}; + // lowercasename -> actualName mapping + fnNames.forEach(symbol => { + fxns[symbol.toLowerCase()] = symbol; + }); - p5._friendlyError(msg, fxns[lowercase]); + for (const prop of Object.keys(context)) { + const lowercase = prop.toLowerCase(); + + // check if the lowercase property name has an entry in fxns, if the + // actual name with correct capitalization doesnt exist in context, + // and if the user-defined symbol is of the type function + if ( + fxns[lowercase] && + !context[fxns[lowercase]] && + typeof context[prop] === 'function' + ) { + const msg = translator('fes.checkUserDefinedFns', { + name: prop, + actualName: fxns[lowercase] + }); + + p5._friendlyError(msg, fxns[lowercase]); + } + } + }; + + /** + * Compares the symbol caught in the ReferenceError to everything in + * misusedAtTopLevel ( all public p5 properties ). + * + * Generates and prints a friendly error message using key: "fes.misspelling". + * + * @method handleMisspelling + * @private + * @param {String} errSym Symbol to whose spelling to check + * @param {Error} error ReferenceError object + * + * @returns {Boolean} tell whether error was likely due to typo + */ + const handleMisspelling = (errSym, error) => { + if (!misusedAtTopLevelCode) { + defineMisusedAtTopLevelCode(); } - } - }; - /** - * Compares the symbol caught in the ReferenceError to everything in - * misusedAtTopLevel ( all public p5 properties ). - * - * Generates and prints a friendly error message using key: "fes.misspelling". - * - * @method handleMisspelling - * @private - * @param {String} errSym Symbol to whose spelling to check - * @param {Error} error ReferenceError object - * - * @returns {Boolean} tell whether error was likely due to typo - */ - const handleMisspelling = (errSym, error) => { - if (!misusedAtTopLevelCode) { - defineMisusedAtTopLevelCode(); - } + const distanceMap = {}; + let min = 999999; + // compute the levenshtein distance for the symbol against all known + // public p5 properties. Find the property with the minimum distance + misusedAtTopLevelCode.forEach(symbol => { + let dist = computeEditDistance(errSym, symbol.name); + if (distanceMap[dist]) distanceMap[dist].push(symbol); + else distanceMap[dist] = [symbol]; - const distanceMap = {}; - let min = 999999; - // compute the levenshtein distance for the symbol against all known - // public p5 properties. Find the property with the minimum distance - misusedAtTopLevelCode.forEach(symbol => { - let dist = computeEditDistance(errSym, symbol.name); - if (distanceMap[dist]) distanceMap[dist].push(symbol); - else distanceMap[dist] = [symbol]; + if (dist < min) min = dist; + }); - if (dist < min) min = dist; - }); + // if the closest match has more "distance" than the max allowed threshold + if (min > Math.min(EDIT_DIST_THRESHOLD, errSym.length)) return false; - // if the closest match has more "distance" than the max allowed threshold - if (min > Math.min(EDIT_DIST_THRESHOLD, errSym.length)) return false; + // Show a message only if the caught symbol and the matched property name + // differ in their name ( either letter difference or difference of case ) + const matchedSymbols = distanceMap[min].filter( + symbol => symbol.name !== errSym + ); + if (matchedSymbols.length !== 0) { + const parsed = p5._getErrorStackParser().parse(error); + let locationObj; + if ( + parsed && + parsed[0] && + parsed[0].fileName && + parsed[0].lineNumber && + parsed[0].columnNumber + ) { + locationObj = { + location: `${parsed[0].fileName}:${parsed[0].lineNumber}:${ + parsed[0].columnNumber + }`, + file: parsed[0].fileName.split('/').slice(-1), + line: parsed[0].lineNumber + }; + } - // Show a message only if the caught symbol and the matched property name - // differ in their name ( either letter difference or difference of case ) - const matchedSymbols = distanceMap[min].filter( - symbol => symbol.name !== errSym - ); - if (matchedSymbols.length !== 0) { - const parsed = p5._getErrorStackParser().parse(error); - let locationObj; - if ( - parsed && - parsed[0] && - parsed[0].fileName && - parsed[0].lineNumber && - parsed[0].columnNumber - ) { - locationObj = { - location: `${parsed[0].fileName}:${parsed[0].lineNumber}:${ - parsed[0].columnNumber - }`, - file: parsed[0].fileName.split('/').slice(-1), - line: parsed[0].lineNumber - }; - } + let msg; + if (matchedSymbols.length === 1) { + // To be used when there is only one closest match. The count parameter + // allows i18n to pick between the keys "fes.misspelling" and + // "fes.misspelling_plural" + msg = translator('fes.misspelling', { + name: errSym, + actualName: matchedSymbols[0].name, + type: matchedSymbols[0].type, + location: locationObj ? translator('fes.location', locationObj) : '', + count: matchedSymbols.length + }); + } else { + // To be used when there are multiple closest matches. Gives each + // suggestion on its own line, the function name followed by a link to + // reference documentation + const suggestions = matchedSymbols + .map(symbol => { + const message = + '▶️ ' + symbol.name + (symbol.type === 'function' ? '()' : ''); + return mapToReference(message, symbol.name); + }) + .join('\n'); + + msg = translator('fes.misspelling', { + name: errSym, + suggestions, + location: locationObj ? translator('fes.location', locationObj) : '', + count: matchedSymbols.length + }); + } - let msg; - if (matchedSymbols.length === 1) { - // To be used when there is only one closest match. The count parameter - // allows i18n to pick between the keys "fes.misspelling" and - // "fes.misspelling_plural" - msg = translator('fes.misspelling', { - name: errSym, - actualName: matchedSymbols[0].name, - type: matchedSymbols[0].type, - location: locationObj ? translator('fes.location', locationObj) : '', - count: matchedSymbols.length + // If there is only one closest match, tell _friendlyError to also add + // a link to the reference documentation. In case of multiple matches, + // this is already done in the suggestions variable, one link for each + // suggestion. + p5._friendlyError( + msg, + matchedSymbols.length === 1 ? matchedSymbols[0].name : undefined + ); + return true; + } + return false; + }; + + /** + * Prints a friendly stacktrace for user-written functions for "global" errors + * + * Generates and prints a friendly error message using key: + * "fes.globalErrors.stackTop", "fes.globalErrors.stackSubseq". + * + * @method printFriendlyStack + * @private + * @param {Array} friendlyStack + */ + const printFriendlyStack = friendlyStack => { + const log = + p5._fesLogger && typeof p5._fesLogger === 'function' + ? p5._fesLogger + : console.log.bind(console); + if (friendlyStack.length > 1) { + let stacktraceMsg = ''; + friendlyStack.forEach((frame, idx) => { + const location = `${frame.fileName}:${frame.lineNumber}:${ + frame.columnNumber + }`; + let frameMsg, + translationObj = { + func: frame.functionName, + line: frame.lineNumber, + location, + file: frame.fileName.split('/').slice(-1) + }; + if (idx === 0) { + frameMsg = translator('fes.globalErrors.stackTop', translationObj); + } else { + frameMsg = translator('fes.globalErrors.stackSubseq', translationObj); + } + stacktraceMsg += frameMsg; }); - } else { - // To be used when there are multiple closest matches. Gives each - // suggestion on its own line, the function name followed by a link to - // reference documentation - const suggestions = matchedSymbols - .map(symbol => { - const message = - '▶️ ' + symbol.name + (symbol.type === 'function' ? '()' : ''); - return mapToReference(message, symbol.name); - }) - .join('\n'); + log(stacktraceMsg); + } + }; + + /** + * Takes a stacktrace array and filters out all frames that show internal p5 + * details. + * + * Generates and prints a friendly error message using key: + * "fes.wrongPreload", "fes.libraryError". + * + * The processed stack is used to find whether the error happened internally + * within the library, and if the error was due to a non-loadX() method + * being used in preload. + * + * "Internally" here means that the exact location of the error (the top of + * the stack) is a piece of code written in the p5.js library (which may or + * may not have been called from the user's sketch). + * + * @method processStack + * @private + * @param {Error} error + * @param {Array} stacktrace + * + * @returns {Array} An array with two elements, [isInternal, friendlyStack] + * isInternal: a boolean value indicating whether the error + * happened internally + * friendlyStack: the filtered (simplified) stacktrace + */ + const processStack = (error, stacktrace) => { + // cannot process a stacktrace that doesn't exist + if (!stacktrace) return [false, null]; + + stacktrace.forEach(frame => { + frame.functionName = frame.functionName || ''; + }); - msg = translator('fes.misspelling', { - name: errSym, - suggestions, - location: locationObj ? translator('fes.location', locationObj) : '', - count: matchedSymbols.length - }); + // isInternal - Did this error happen inside the library + let isInternal = false; + let p5FileName, friendlyStack, currentEntryPoint; + + // Intentionally throw an error that we catch so that we can check the name + // of the current file. Any errors we see from this file, we treat as + // internal errors. + try { + throw new Error(); + } catch (testError) { + const testStacktrace = p5._getErrorStackParser().parse(testError); + p5FileName = testStacktrace[0].fileName; } - // If there is only one closest match, tell _friendlyError to also add - // a link to the reference documentation. In case of multiple matches, - // this is already done in the suggestions variable, one link for each - // suggestion. - p5._friendlyError( - msg, - matchedSymbols.length === 1 ? matchedSymbols[0].name : undefined - ); - return true; - } - return false; - }; + for (let i = stacktrace.length - 1; i >= 0; i--) { + let splitted = stacktrace[i].functionName.split('.'); + if (entryPoints.includes(splitted[splitted.length - 1])) { + // remove everything below an entry point function (setup, draw, etc). + // (it's usually the internal initialization calls) + friendlyStack = stacktrace.slice(0, i + 1); + currentEntryPoint = splitted[splitted.length - 1]; + // We call the error "internal" if the source of the error was a + // function from within the p5.js library file, but called from the + // user's code directly. We only need to check the topmost frame in + // the stack trace since any function internal to p5 should pass this + // check, not just public p5 functions. + if (stacktrace[0].fileName === p5FileName) { + isInternal = true; + break; + } + break; + } + } - /** - * Prints a friendly stacktrace for user-written functions for "global" errors - * - * Generates and prints a friendly error message using key: - * "fes.globalErrors.stackTop", "fes.globalErrors.stackSubseq". - * - * @method printFriendlyStack - * @private - * @param {Array} friendlyStack - */ - const printFriendlyStack = friendlyStack => { - const log = - p5._fesLogger && typeof p5._fesLogger === 'function' - ? p5._fesLogger - : console.log.bind(console); - if (friendlyStack.length > 1) { - let stacktraceMsg = ''; - friendlyStack.forEach((frame, idx) => { - const location = `${frame.fileName}:${frame.lineNumber}:${ - frame.columnNumber - }`; - let frameMsg, - translationObj = { - func: frame.functionName, - line: frame.lineNumber, - location, - file: frame.fileName.split('/').slice(-1) + // in some cases ( errors in promises, callbacks, etc), no entry-point + // function may be found in the stacktrace. In that case just use the + // entire stacktrace for friendlyStack + if (!friendlyStack) friendlyStack = stacktrace; + + if (isInternal) { + // the frameIndex property is added before the filter, so frameIndex + // corresponds to the index of a frame in the original stacktrace. + // Then we filter out all frames which belong to the file that contains + // the p5 library + friendlyStack = friendlyStack + .map((frame, index) => { + frame.frameIndex = index; + return frame; + }) + .filter(frame => frame.fileName !== p5FileName); + + // a weird case, if for some reason we can't identify the function called + // from user's code + if (friendlyStack.length === 0) return [true, null]; + + // get the function just above the topmost frame in the friendlyStack. + // i.e the name of the library function called from user's code + const func = stacktrace[friendlyStack[0].frameIndex - 1].functionName + .split('.') + .slice(-1)[0]; + + // Try and get the location (line no.) from the top element of the stack + let locationObj; + if ( + friendlyStack[0].fileName && + friendlyStack[0].lineNumber && + friendlyStack[0].columnNumber + ) { + locationObj = { + location: `${friendlyStack[0].fileName}:${ + friendlyStack[0].lineNumber + }:${friendlyStack[0].columnNumber}`, + file: friendlyStack[0].fileName.split('/').slice(-1), + line: friendlyStack[0].lineNumber }; - if (idx === 0) { - frameMsg = translator('fes.globalErrors.stackTop', translationObj); + + // if already handled by another part of the FES, don't handle again + if (p5._fesLogCache[locationObj.location]) return [true, null]; + } + + // Check if the error is due to a non loadX method being used incorrectly + // in preload + if ( + currentEntryPoint === 'preload' && + fn._preloadMethods[func] == null + ) { + p5._friendlyError( + translator('fes.wrongPreload', { + func, + location: locationObj + ? translator('fes.location', locationObj) + : '', + error: error.message + }), + 'preload' + ); } else { - frameMsg = translator('fes.globalErrors.stackSubseq', translationObj); + // Library error + p5._friendlyError( + translator('fes.libraryError', { + func, + location: locationObj + ? translator('fes.location', locationObj) + : '', + error: error.message + }), + func + ); } - stacktraceMsg += frameMsg; - }); - log(stacktraceMsg); - } - }; - /** - * Takes a stacktrace array and filters out all frames that show internal p5 - * details. - * - * Generates and prints a friendly error message using key: - * "fes.wrongPreload", "fes.libraryError". - * - * The processed stack is used to find whether the error happened internally - * within the library, and if the error was due to a non-loadX() method - * being used in preload. - * - * "Internally" here means that the exact location of the error (the top of - * the stack) is a piece of code written in the p5.js library (which may or - * may not have been called from the user's sketch). - * - * @method processStack - * @private - * @param {Error} error - * @param {Array} stacktrace - * - * @returns {Array} An array with two elements, [isInternal, friendlyStack] - * isInternal: a boolean value indicating whether the error - * happened internally - * friendlyStack: the filtered (simplified) stacktrace - */ - const processStack = (error, stacktrace) => { - // cannot process a stacktrace that doesn't exist - if (!stacktrace) return [false, null]; + // Finally, if it's an internal error, print the friendlyStack + // ( fesErrorMonitor won't handle this error ) + if (friendlyStack && friendlyStack.length) { + printFriendlyStack(friendlyStack); + } + } + return [isInternal, friendlyStack]; + }; + + /** + * Handles "global" errors that the browser catches. + * + * Called when an error event happens and detects the type of error. + * + * Generates and prints a friendly error message using key: + * "fes.globalErrors.syntax.[*]", "fes.globalErrors.reference.[*]", + * "fes.globalErrors.type.[*]". + * + * @method fesErrorMonitor + * @private + * @param {*} e Event object to extract error details from + */ + const fesErrorMonitor = e => { + if (p5.disableFriendlyErrors) return; + // Try to get the error object from e + let error; + if (e instanceof Error) { + error = e; + } else if (e instanceof ErrorEvent) { + error = e.error; + } else if (e instanceof PromiseRejectionEvent) { + error = e.reason; + if (!(error instanceof Error)) return; + } + if (!error) return; - stacktrace.forEach(frame => { - frame.functionName = frame.functionName || ''; - }); + let stacktrace = p5._getErrorStackParser().parse(error); + // process the stacktrace from the browser and simplify it to give + // friendlyStack. + let [isInternal, friendlyStack] = processStack(error, stacktrace); - // isInternal - Did this error happen inside the library - let isInternal = false; - let p5FileName, friendlyStack, currentEntryPoint; - - // Intentionally throw an error that we catch so that we can check the name - // of the current file. Any errors we see from this file, we treat as - // internal errors. - try { - throw new Error(); - } catch (testError) { - const testStacktrace = p5._getErrorStackParser().parse(testError); - p5FileName = testStacktrace[0].fileName; - } + // if this is an internal library error, the type of the error is not relevant, + // only the user code that lead to it is. + if (isInternal) { + return; + } - for (let i = stacktrace.length - 1; i >= 0; i--) { - let splitted = stacktrace[i].functionName.split('.'); - if (entryPoints.includes(splitted[splitted.length - 1])) { - // remove everything below an entry point function (setup, draw, etc). - // (it's usually the internal initialization calls) - friendlyStack = stacktrace.slice(0, i + 1); - currentEntryPoint = splitted[splitted.length - 1]; - // We call the error "internal" if the source of the error was a - // function from within the p5.js library file, but called from the - // user's code directly. We only need to check the topmost frame in - // the stack trace since any function internal to p5 should pass this - // check, not just public p5 functions. - if (stacktrace[0].fileName === p5FileName) { - isInternal = true; + const errList = errorTable[error.name]; + if (!errList) return; // this type of error can't be handled yet + let matchedError; + for (const obj of errList) { + let string = obj.msg; + // capture the primary symbol mentioned in the error + string = string.replace(new RegExp('{{}}', 'g'), '([a-zA-Z0-9_]+)'); + string = string.replace(new RegExp('{{.}}', 'g'), '(.+)'); + string = string.replace(new RegExp('{}', 'g'), '(?:[a-zA-Z0-9_]+)'); + let matched = error.message.match(string); + + if (matched) { + matchedError = Object.assign({}, obj); + matchedError.match = matched; break; } - break; } - } - - // in some cases ( errors in promises, callbacks, etc), no entry-point - // function may be found in the stacktrace. In that case just use the - // entire stacktrace for friendlyStack - if (!friendlyStack) friendlyStack = stacktrace; - - if (isInternal) { - // the frameIndex property is added before the filter, so frameIndex - // corresponds to the index of a frame in the original stacktrace. - // Then we filter out all frames which belong to the file that contains - // the p5 library - friendlyStack = friendlyStack - .map((frame, index) => { - frame.frameIndex = index; - return frame; - }) - .filter(frame => frame.fileName !== p5FileName); - - // a weird case, if for some reason we can't identify the function called - // from user's code - if (friendlyStack.length === 0) return [true, null]; - // get the function just above the topmost frame in the friendlyStack. - // i.e the name of the library function called from user's code - const func = stacktrace[friendlyStack[0].frameIndex - 1].functionName - .split('.') - .slice(-1)[0]; + if (!matchedError) return; - // Try and get the location (line no.) from the top element of the stack + // Try and get the location from the top element of the stack let locationObj; if ( - friendlyStack[0].fileName && - friendlyStack[0].lineNumber && - friendlyStack[0].columnNumber + stacktrace && + stacktrace[0].fileName && + stacktrace[0].lineNumber && + stacktrace[0].columnNumber ) { locationObj = { - location: `${friendlyStack[0].fileName}:${ - friendlyStack[0].lineNumber - }:${friendlyStack[0].columnNumber}`, - file: friendlyStack[0].fileName.split('/').slice(-1), + location: `${stacktrace[0].fileName}:${stacktrace[0].lineNumber}:${ + stacktrace[0].columnNumber + }`, + file: stacktrace[0].fileName.split('/').slice(-1), line: friendlyStack[0].lineNumber }; - - // if already handled by another part of the FES, don't handle again - if (p5._fesLogCache[locationObj.location]) return [true, null]; } - // Check if the error is due to a non loadX method being used incorrectly - // in preload - if ( - currentEntryPoint === 'preload' && - p5.prototype._preloadMethods[func] == null - ) { - p5._friendlyError( - translator('fes.wrongPreload', { - func, - location: locationObj - ? translator('fes.location', locationObj) - : '', - error: error.message - }), - 'preload' - ); - } else { - // Library error - p5._friendlyError( - translator('fes.libraryError', { - func, - location: locationObj - ? translator('fes.location', locationObj) - : '', - error: error.message - }), - func - ); - } - - // Finally, if it's an internal error, print the friendlyStack - // ( fesErrorMonitor won't handle this error ) - if (friendlyStack && friendlyStack.length) { - printFriendlyStack(friendlyStack); - } - } - return [isInternal, friendlyStack]; - }; - - /** - * Handles "global" errors that the browser catches. - * - * Called when an error event happens and detects the type of error. - * - * Generates and prints a friendly error message using key: - * "fes.globalErrors.syntax.[*]", "fes.globalErrors.reference.[*]", - * "fes.globalErrors.type.[*]". - * - * @method fesErrorMonitor - * @private - * @param {*} e Event object to extract error details from - */ - const fesErrorMonitor = e => { - if (p5.disableFriendlyErrors) return; - // Try to get the error object from e - let error; - if (e instanceof Error) { - error = e; - } else if (e instanceof ErrorEvent) { - error = e.error; - } else if (e instanceof PromiseRejectionEvent) { - error = e.reason; - if (!(error instanceof Error)) return; - } - if (!error) return; - - let stacktrace = p5._getErrorStackParser().parse(error); - // process the stacktrace from the browser and simplify it to give - // friendlyStack. - let [isInternal, friendlyStack] = processStack(error, stacktrace); - - // if this is an internal library error, the type of the error is not relevant, - // only the user code that lead to it is. - if (isInternal) { - return; - } - - const errList = errorTable[error.name]; - if (!errList) return; // this type of error can't be handled yet - let matchedError; - for (const obj of errList) { - let string = obj.msg; - // capture the primary symbol mentioned in the error - string = string.replace(new RegExp('{{}}', 'g'), '([a-zA-Z0-9_]+)'); - string = string.replace(new RegExp('{{.}}', 'g'), '(.+)'); - string = string.replace(new RegExp('{}', 'g'), '(?:[a-zA-Z0-9_]+)'); - let matched = error.message.match(string); - - if (matched) { - matchedError = Object.assign({}, obj); - matchedError.match = matched; - break; - } - } - - if (!matchedError) return; - - // Try and get the location from the top element of the stack - let locationObj; - if ( - stacktrace && - stacktrace[0].fileName && - stacktrace[0].lineNumber && - stacktrace[0].columnNumber - ) { - locationObj = { - location: `${stacktrace[0].fileName}:${stacktrace[0].lineNumber}:${ - stacktrace[0].columnNumber - }`, - file: stacktrace[0].fileName.split('/').slice(-1), - line: friendlyStack[0].lineNumber - }; - } - - switch (error.name) { - case 'SyntaxError': { - // We can't really do much with syntax errors other than try to use - // a simpler framing of the error message. The stack isn't available - // for syntax errors - switch (matchedError.type) { - case 'INVALIDTOKEN': { - //Error if there is an invalid or unexpected token that doesn't belong at this position in the code - //let x = “not a string”; -> string not in proper quotes - let url = - 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Illegal_character#What_went_wrong'; - p5._friendlyError( - translator('fes.globalErrors.syntax.invalidToken', { - url - }) - ); - break; - } - case 'UNEXPECTEDTOKEN': { - //Error if a specific language construct(, { ; etc) was expected, but something else was provided - //for (let i = 0; i < 5,; ++i) -> a comma after i<5 instead of a semicolon - let url = - 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Unexpected_token#What_went_wrong'; - p5._friendlyError( - translator('fes.globalErrors.syntax.unexpectedToken', { - url - }) - ); - break; - } - case 'REDECLAREDVARIABLE': { - //Error if a variable is redeclared by the user. Example=> - //let a = 10; - //let a = 100; - let errSym = matchedError.match[1]; - let url = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Redeclared_parameter#what_went_wrong'; - p5._friendlyError( - translator('fes.globalErrors.syntax.redeclaredVariable', { - symbol: errSym, - url - }) - ); - break; - } - case 'MISSINGINITIALIZER': { - //Error if a const variable is not initialized during declaration - //Example => const a; - let url = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Missing_initializer_in_const#what_went_wrong'; - p5._friendlyError( - translator('fes.globalErrors.syntax.missingInitializer', { - url - }) - ); - break; - } - case 'BADRETURNORYIELD': { - //Error when a return statement is misplaced(usually outside of a function) - // const a = function(){ - // ..... - // } - // return; -> misplaced return statement - let url = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Bad_return_or_yield#what_went_wrong'; - p5._friendlyError( - translator('fes.globalErrors.syntax.badReturnOrYield', { - url - }) - ); - break; + switch (error.name) { + case 'SyntaxError': { + // We can't really do much with syntax errors other than try to use + // a simpler framing of the error message. The stack isn't available + // for syntax errors + switch (matchedError.type) { + case 'INVALIDTOKEN': { + //Error if there is an invalid or unexpected token that doesn't belong at this position in the code + //let x = “not a string”; -> string not in proper quotes + let url = + 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Illegal_character#What_went_wrong'; + p5._friendlyError( + translator('fes.globalErrors.syntax.invalidToken', { + url + }) + ); + break; + } + case 'UNEXPECTEDTOKEN': { + //Error if a specific language construct(, { ; etc) was expected, but something else was provided + //for (let i = 0; i < 5,; ++i) -> a comma after i<5 instead of a semicolon + let url = + 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Unexpected_token#What_went_wrong'; + p5._friendlyError( + translator('fes.globalErrors.syntax.unexpectedToken', { + url + }) + ); + break; + } + case 'REDECLAREDVARIABLE': { + //Error if a variable is redeclared by the user. Example=> + //let a = 10; + //let a = 100; + let errSym = matchedError.match[1]; + let url = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Redeclared_parameter#what_went_wrong'; + p5._friendlyError( + translator('fes.globalErrors.syntax.redeclaredVariable', { + symbol: errSym, + url + }) + ); + break; + } + case 'MISSINGINITIALIZER': { + //Error if a const variable is not initialized during declaration + //Example => const a; + let url = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Missing_initializer_in_const#what_went_wrong'; + p5._friendlyError( + translator('fes.globalErrors.syntax.missingInitializer', { + url + }) + ); + break; + } + case 'BADRETURNORYIELD': { + //Error when a return statement is misplaced(usually outside of a function) + // const a = function(){ + // ..... + // } + // return; -> misplaced return statement + let url = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Bad_return_or_yield#what_went_wrong'; + p5._friendlyError( + translator('fes.globalErrors.syntax.badReturnOrYield', { + url + }) + ); + break; + } } + break; } - break; - } - case 'ReferenceError': { - switch (matchedError.type) { - case 'NOTDEFINED': { - //Error if there is a non-existent variable referenced somewhere - //let a = 10; - //console.log(x); - let errSym = matchedError.match[1]; - - if (errSym && handleMisspelling(errSym, error)) { + case 'ReferenceError': { + switch (matchedError.type) { + case 'NOTDEFINED': { + //Error if there is a non-existent variable referenced somewhere + //let a = 10; + //console.log(x); + let errSym = matchedError.match[1]; + + if (errSym && handleMisspelling(errSym, error)) { + break; + } + + // if the flow gets this far, this is likely not a misspelling + // of a p5 property/function + let url = 'https://p5js.org/examples/data-variable-scope.html'; + p5._friendlyError( + translator('fes.globalErrors.reference.notDefined', { + url, + symbol: errSym, + location: locationObj + ? translator('fes.location', locationObj) + : '' + }) + ); + + if (friendlyStack) printFriendlyStack(friendlyStack); break; } + case 'CANNOTACCESS': { + //Error if a lexical variable was accessed before it was initialized + //console.log(a); -> variable accessed before it was initialized + //let a=100; + let errSym = matchedError.match[1]; + let url = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_access_lexical_declaration_before_init#what_went_wrong'; + p5._friendlyError( + translator('fes.globalErrors.reference.cannotAccess', { + url, + symbol: errSym, + location: locationObj + ? translator('fes.location', locationObj) + : '' + }) + ); - // if the flow gets this far, this is likely not a misspelling - // of a p5 property/function - let url = 'https://p5js.org/examples/data-variable-scope.html'; - p5._friendlyError( - translator('fes.globalErrors.reference.notDefined', { - url, - symbol: errSym, - location: locationObj - ? translator('fes.location', locationObj) - : '' - }) - ); - - if (friendlyStack) printFriendlyStack(friendlyStack); - break; + if (friendlyStack) printFriendlyStack(friendlyStack); + break; + } } - case 'CANNOTACCESS': { - //Error if a lexical variable was accessed before it was initialized - //console.log(a); -> variable accessed before it was initialized - //let a=100; - let errSym = matchedError.match[1]; - let url = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_access_lexical_declaration_before_init#what_went_wrong'; - p5._friendlyError( - translator('fes.globalErrors.reference.cannotAccess', { + break; + } + + case 'TypeError': { + switch (matchedError.type) { + case 'NOTFUNC': { + //Error when some code expects you to provide a function, but that didn't happen + //let a = document.getElementByID('foo'); -> getElementById instead of getElementByID + let errSym = matchedError.match[1]; + let splitSym = errSym.split('.'); + let url = + 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_a_function#What_went_wrong'; + + // if errSym is aa.bb.cc , symbol would be cc and obj would aa.bb + let translationObj = { url, - symbol: errSym, + symbol: splitSym[splitSym.length - 1], + obj: splitSym.slice(0, splitSym.length - 1).join('.'), location: locationObj ? translator('fes.location', locationObj) : '' - }) - ); - - if (friendlyStack) printFriendlyStack(friendlyStack); - break; - } - } - break; - } - - case 'TypeError': { - switch (matchedError.type) { - case 'NOTFUNC': { - //Error when some code expects you to provide a function, but that didn't happen - //let a = document.getElementByID('foo'); -> getElementById instead of getElementByID - let errSym = matchedError.match[1]; - let splitSym = errSym.split('.'); - let url = - 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_a_function#What_went_wrong'; - - // if errSym is aa.bb.cc , symbol would be cc and obj would aa.bb - let translationObj = { - url, - symbol: splitSym[splitSym.length - 1], - obj: splitSym.slice(0, splitSym.length - 1).join('.'), - location: locationObj - ? translator('fes.location', locationObj) - : '' - }; - - // There are two cases to handle here. When the function is called - // as a property of an object and when it's called independently. - // Both have different explanations. - if (splitSym.length > 1) { + }; + + // There are two cases to handle here. When the function is called + // as a property of an object and when it's called independently. + // Both have different explanations. + if (splitSym.length > 1) { + p5._friendlyError( + translator('fes.globalErrors.type.notfuncObj', translationObj) + ); + } else { + p5._friendlyError( + translator('fes.globalErrors.type.notfunc', translationObj) + ); + } + + if (friendlyStack) printFriendlyStack(friendlyStack); + break; + } + case 'READNULL': { + //Error if a property of null is accessed + //let a = null; + //console.log(a.property); -> a is null + let errSym = matchedError.match[1]; + let url = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_access_property#what_went_wrong'; + /*let url2 = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null';*/ p5._friendlyError( - translator('fes.globalErrors.type.notfuncObj', translationObj) + translator('fes.globalErrors.type.readFromNull', { + url, + symbol: errSym, + location: locationObj + ? translator('fes.location', locationObj) + : '' + }) ); - } else { + + if (friendlyStack) printFriendlyStack(friendlyStack); + break; + } + case 'READUDEFINED': { + //Error if a property of undefined is accessed + //let a; -> default value of a is undefined + //console.log(a.property); -> a is undefined + let errSym = matchedError.match[1]; + let url = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_access_property#what_went_wrong'; + /*let url2 = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined#description';*/ p5._friendlyError( - translator('fes.globalErrors.type.notfunc', translationObj) + translator('fes.globalErrors.type.readFromUndefined', { + url, + symbol: errSym, + location: locationObj + ? translator('fes.location', locationObj) + : '' + }) ); + + if (friendlyStack) printFriendlyStack(friendlyStack); + break; } + case 'CONSTASSIGN': { + //Error when a const variable is reassigned a value + //const a = 100; + //a=10; + let url = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_const_assignment#what_went_wrong'; + p5._friendlyError( + translator('fes.globalErrors.type.constAssign', { + url, + location: locationObj + ? translator('fes.location', locationObj) + : '' + }) + ); - if (friendlyStack) printFriendlyStack(friendlyStack); - break; + if (friendlyStack) printFriendlyStack(friendlyStack); + break; + } } - case 'READNULL': { - //Error if a property of null is accessed - //let a = null; - //console.log(a.property); -> a is null - let errSym = matchedError.match[1]; - let url = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_access_property#what_went_wrong'; - /*let url2 = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null';*/ - p5._friendlyError( - translator('fes.globalErrors.type.readFromNull', { - url, - symbol: errSym, - location: locationObj - ? translator('fes.location', locationObj) - : '' - }) - ); + } + } + }; + + p5._fesErrorMonitor = fesErrorMonitor; + p5._checkForUserDefinedFunctions = checkForUserDefinedFunctions; + + // logger for testing purposes. + p5._fesLogger = null; + p5._fesLogCache = {}; + + window.addEventListener('load', checkForUserDefinedFunctions, false); + window.addEventListener('error', p5._fesErrorMonitor, false); + window.addEventListener('unhandledrejection', p5._fesErrorMonitor, false); + + /** + * Prints out all the colors in the color pallete with white text. + * For color blindness testing. + */ + /* function testColors() { + const str = 'A box of biscuits, a box of mixed biscuits and a biscuit mixer'; + p5._friendlyError(str, 'print', '#ED225D'); // p5.js magenta + p5._friendlyError(str, 'print', '#2D7BB6'); // p5.js blue + p5._friendlyError(str, 'print', '#EE9900'); // p5.js orange + p5._friendlyError(str, 'print', '#A67F59'); // p5.js light brown + p5._friendlyError(str, 'print', '#704F21'); // p5.js gold + p5._friendlyError(str, 'print', '#1CC581'); // auto cyan + p5._friendlyError(str, 'print', '#FF6625'); // auto orange + p5._friendlyError(str, 'print', '#79EB22'); // auto green + p5._friendlyError(str, 'print', '#B40033'); // p5.js darkened magenta + p5._friendlyError(str, 'print', '#084B7F'); // p5.js darkened blue + p5._friendlyError(str, 'print', '#945F00'); // p5.js darkened orange + p5._friendlyError(str, 'print', '#6B441D'); // p5.js darkened brown + p5._friendlyError(str, 'print', '#2E1B00'); // p5.js darkened gold + p5._friendlyError(str, 'print', '#008851'); // auto dark cyan + p5._friendlyError(str, 'print', '#C83C00'); // auto dark orange + p5._friendlyError(str, 'print', '#4DB200'); // auto dark green + } */ + } - if (friendlyStack) printFriendlyStack(friendlyStack); - break; - } - case 'READUDEFINED': { - //Error if a property of undefined is accessed - //let a; -> default value of a is undefined - //console.log(a.property); -> a is undefined - let errSym = matchedError.match[1]; - let url = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_access_property#what_went_wrong'; - /*let url2 = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined#description';*/ - p5._friendlyError( - translator('fes.globalErrors.type.readFromUndefined', { - url, - symbol: errSym, - location: locationObj - ? translator('fes.location', locationObj) - : '' - }) - ); + // This is a lazily-defined list of p5 symbols that may be + // misused by beginners at top-level code, outside of setup/draw. We'd like + // to detect these errors and help the user by suggesting they move them + // into setup/draw. + // + // For more details, see https://github.com/processing/p5.js/issues/1121. + misusedAtTopLevelCode = null; + const FAQ_URL = + 'https://github.com/processing/p5.js/wiki/p5.js-overview#why-cant-i-assign-variables-using-p5-functions-and-variables-before-setup'; - if (friendlyStack) printFriendlyStack(friendlyStack); - break; + /** + * A helper function for populating misusedAtTopLevel list. + * + * @method defineMisusedAtTopLevelCode + * @private + */ + defineMisusedAtTopLevelCode = () => { + const uniqueNamesFound = {}; + + const getSymbols = obj => + Object.getOwnPropertyNames(obj) + .filter(name => { + if (name[0] === '_') { + return false; + } + if (name in uniqueNamesFound) { + return false; } - case 'CONSTASSIGN': { - //Error when a const variable is reassigned a value - //const a = 100; - //a=10; - let url = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_const_assignment#what_went_wrong'; - p5._friendlyError( - translator('fes.globalErrors.type.constAssign', { - url, - location: locationObj - ? translator('fes.location', locationObj) - : '' - }) - ); - if (friendlyStack) printFriendlyStack(friendlyStack); - break; + uniqueNamesFound[name] = true; + + return true; + }) + .map(name => { + let type; + + if (typeof obj[name] === 'function') { + type = 'function'; + } else if (name === name.toUpperCase()) { + type = 'constant'; + } else { + type = 'variable'; } - } - } - } - }; - p5._fesErrorMonitor = fesErrorMonitor; - p5._checkForUserDefinedFunctions = checkForUserDefinedFunctions; + return { name, type }; + }); - // logger for testing purposes. - p5._fesLogger = null; - p5._fesLogCache = {}; + misusedAtTopLevelCode = [].concat( + getSymbols(fn), + // At present, p5 only adds its constants to fn during + // construction, which may not have happened at the time a + // ReferenceError is thrown, so we'll manually add them to our list. + getSymbols(contants) + ); - window.addEventListener('load', checkForUserDefinedFunctions, false); - window.addEventListener('error', p5._fesErrorMonitor, false); - window.addEventListener('unhandledrejection', p5._fesErrorMonitor, false); + // This will ultimately ensure that we report the most specific error + // possible to the user, e.g. advising them about HALF_PI instead of PI + // when their code misuses the former. + misusedAtTopLevelCode.sort((a, b) => b.name.length - a.name.length); + }; /** - * Prints out all the colors in the color pallete with white text. - * For color blindness testing. + * Detects browser level error event for p5 constants/functions used outside + * of setup() and draw(). + * + * Generates and prints a friendly error message using key: + * "fes.misusedTopLevel". + * + * @method helpForMisusedAtTopLevelCode + * @private + * @param {Event} e Error event + * @param {Boolean} log false + * + * @returns {Boolean} true */ - /* function testColors() { - const str = 'A box of biscuits, a box of mixed biscuits and a biscuit mixer'; - p5._friendlyError(str, 'print', '#ED225D'); // p5.js magenta - p5._friendlyError(str, 'print', '#2D7BB6'); // p5.js blue - p5._friendlyError(str, 'print', '#EE9900'); // p5.js orange - p5._friendlyError(str, 'print', '#A67F59'); // p5.js light brown - p5._friendlyError(str, 'print', '#704F21'); // p5.js gold - p5._friendlyError(str, 'print', '#1CC581'); // auto cyan - p5._friendlyError(str, 'print', '#FF6625'); // auto orange - p5._friendlyError(str, 'print', '#79EB22'); // auto green - p5._friendlyError(str, 'print', '#B40033'); // p5.js darkened magenta - p5._friendlyError(str, 'print', '#084B7F'); // p5.js darkened blue - p5._friendlyError(str, 'print', '#945F00'); // p5.js darkened orange - p5._friendlyError(str, 'print', '#6B441D'); // p5.js darkened brown - p5._friendlyError(str, 'print', '#2E1B00'); // p5.js darkened gold - p5._friendlyError(str, 'print', '#008851'); // auto dark cyan - p5._friendlyError(str, 'print', '#C83C00'); // auto dark orange - p5._friendlyError(str, 'print', '#4DB200'); // auto dark green - } */ -} - -// This is a lazily-defined list of p5 symbols that may be -// misused by beginners at top-level code, outside of setup/draw. We'd like -// to detect these errors and help the user by suggesting they move them -// into setup/draw. -// -// For more details, see https://github.com/processing/p5.js/issues/1121. -misusedAtTopLevelCode = null; -const FAQ_URL = - 'https://github.com/processing/p5.js/wiki/p5.js-overview#why-cant-i-assign-variables-using-p5-functions-and-variables-before-setup'; - -/** - * A helper function for populating misusedAtTopLevel list. - * - * @method defineMisusedAtTopLevelCode - * @private - */ -defineMisusedAtTopLevelCode = () => { - const uniqueNamesFound = {}; - - const getSymbols = obj => - Object.getOwnPropertyNames(obj) - .filter(name => { - if (name[0] === '_') { - return false; - } - if (name in uniqueNamesFound) { - return false; - } + const helpForMisusedAtTopLevelCode = (e, log) => { + if (!log) { + log = console.log.bind(console); + } - uniqueNamesFound[name] = true; + if (!misusedAtTopLevelCode) { + defineMisusedAtTopLevelCode(); + } - return true; - }) - .map(name => { - let type; - - if (typeof obj[name] === 'function') { - type = 'function'; - } else if (name === name.toUpperCase()) { - type = 'constant'; + // If we find that we're logging lots of false positives, we can + // uncomment the following code to avoid displaying anything if the + // user's code isn't likely to be using p5's global mode. (Note that + // setup/draw are more likely to be defined due to JS function hoisting.) + // + //if (!('setup' in window || 'draw' in window)) { + // return; + //} + + misusedAtTopLevelCode.some(symbol => { + // Note that while just checking for the occurrence of the + // symbol name in the error message could result in false positives, + // a more rigorous test is difficult because different browsers + // log different messages, and the format of those messages may + // change over time. + // + // For example, if the user uses 'PI' in their code, it may result + // in any one of the following messages: + // + // * 'PI' is undefined (Microsoft Edge) + // * ReferenceError: PI is undefined (Firefox) + // * Uncaught ReferenceError: PI is not defined (Chrome) + + if (e.message && e.message.match(`\\W?${symbol.name}\\W`) !== null) { + const symbolName = + symbol.type === 'function' ? `${symbol.name}()` : symbol.name; + if (typeof IS_MINIFIED !== 'undefined') { + log( + `Did you just try to use p5.js's ${symbolName} ${ + symbol.type + }? If so, you may want to move it into your sketch's setup() function.\n\nFor more details, see: ${FAQ_URL}` + ); } else { - type = 'variable'; + log( + translator('fes.misusedTopLevel', { + symbolName, + symbolType: symbol.type, + url: FAQ_URL + }) + ); } + return true; + } + }); + }; - return { name, type }; - }); - - misusedAtTopLevelCode = [].concat( - getSymbols(p5.prototype), - // At present, p5 only adds its constants to p5.prototype during - // construction, which may not have happened at the time a - // ReferenceError is thrown, so we'll manually add them to our list. - getSymbols(contants) - ); + // Exposing this primarily for unit testing. + fn._helpForMisusedAtTopLevelCode = helpForMisusedAtTopLevelCode; - // This will ultimately ensure that we report the most specific error - // possible to the user, e.g. advising them about HALF_PI instead of PI - // when their code misuses the former. - misusedAtTopLevelCode.sort((a, b) => b.name.length - a.name.length); -}; + if (document.readyState !== 'complete') { + window.addEventListener('error', helpForMisusedAtTopLevelCode, false); -/** - * Detects browser level error event for p5 constants/functions used outside - * of setup() and draw(). - * - * Generates and prints a friendly error message using key: - * "fes.misusedTopLevel". - * - * @method helpForMisusedAtTopLevelCode - * @private - * @param {Event} e Error event - * @param {Boolean} log false - * - * @returns {Boolean} true - */ -const helpForMisusedAtTopLevelCode = (e, log) => { - if (!log) { - log = console.log.bind(console); + // Our job is only to catch ReferenceErrors that are thrown when + // global (non-instance mode) p5 APIs are used at the top-level + // scope of a file, so we'll unbind our error listener now to make + // sure we don't log false positives later. + window.addEventListener('load', () => { + window.removeEventListener('error', helpForMisusedAtTopLevelCode, false); + }); } +} - if (!misusedAtTopLevelCode) { - defineMisusedAtTopLevelCode(); - } +export default fesCore; - // If we find that we're logging lots of false positives, we can - // uncomment the following code to avoid displaying anything if the - // user's code isn't likely to be using p5's global mode. (Note that - // setup/draw are more likely to be defined due to JS function hoisting.) - // - //if (!('setup' in window || 'draw' in window)) { - // return; - //} - - misusedAtTopLevelCode.some(symbol => { - // Note that while just checking for the occurrence of the - // symbol name in the error message could result in false positives, - // a more rigorous test is difficult because different browsers - // log different messages, and the format of those messages may - // change over time. - // - // For example, if the user uses 'PI' in their code, it may result - // in any one of the following messages: - // - // * 'PI' is undefined (Microsoft Edge) - // * ReferenceError: PI is undefined (Firefox) - // * Uncaught ReferenceError: PI is not defined (Chrome) - - if (e.message && e.message.match(`\\W?${symbol.name}\\W`) !== null) { - const symbolName = - symbol.type === 'function' ? `${symbol.name}()` : symbol.name; - if (typeof IS_MINIFIED !== 'undefined') { - log( - `Did you just try to use p5.js's ${symbolName} ${ - symbol.type - }? If so, you may want to move it into your sketch's setup() function.\n\nFor more details, see: ${FAQ_URL}` - ); - } else { - log( - translator('fes.misusedTopLevel', { - symbolName, - symbolType: symbol.type, - url: FAQ_URL - }) - ); - } - return true; - } - }); -}; - -// Exposing this primarily for unit testing. -p5.prototype._helpForMisusedAtTopLevelCode = helpForMisusedAtTopLevelCode; - -if (document.readyState !== 'complete') { - window.addEventListener('error', helpForMisusedAtTopLevelCode, false); - - // Our job is only to catch ReferenceErrors that are thrown when - // global (non-instance mode) p5 APIs are used at the top-level - // scope of a file, so we'll unbind our error listener now to make - // sure we don't log false positives later. - window.addEventListener('load', () => { - window.removeEventListener('error', helpForMisusedAtTopLevelCode, false); - }); +if (typeof p5 !== 'undefined') { + fesCore(p5, p5.prototype); } - -export default p5; diff --git a/src/core/friendly_errors/file_errors.js b/src/core/friendly_errors/file_errors.js index 677d7a61b9..8f212c8355 100644 --- a/src/core/friendly_errors/file_errors.js +++ b/src/core/friendly_errors/file_errors.js @@ -2,12 +2,9 @@ * @for p5 * @requires core */ -import p5 from '../main'; import { translator } from '../internationalization'; -if (typeof IS_MINIFIED !== 'undefined') { - p5._friendlyFileLoadError = () => {}; -} else { +function fileErrors(p5, fn){ // mapping used by `_friendlyFileLoadError` const fileLoadErrorCases = (num, filePath) => { const suggestion = translator('fes.fileLoadError.suggestion', { @@ -76,6 +73,7 @@ if (typeof IS_MINIFIED !== 'undefined') { }; } }; + /** * Called internally if there is an error during file loading. * @@ -93,4 +91,8 @@ if (typeof IS_MINIFIED !== 'undefined') { }; } -export default p5; +export default fileErrors; + +if (typeof p5 !== 'undefined') { + fileErrors(p5, p5.prototype); +} diff --git a/src/core/friendly_errors/index.js b/src/core/friendly_errors/index.js index 8f1b0e56e0..d69a3c604e 100644 --- a/src/core/friendly_errors/index.js +++ b/src/core/friendly_errors/index.js @@ -1,7 +1,13 @@ +import fesCore from './fes_core'; +import stacktrace from './stacktrace'; import validateParams from './param_validator.js'; import sketchVerifier from './sketch_verifier.js'; +import fileErrors from './file_errors'; export default function (p5) { + p5.registerAddon(fesCore); + p5.registerAddon(stacktrace); p5.registerAddon(validateParams); p5.registerAddon(sketchVerifier); -} \ No newline at end of file + p5.registerAddon(fileErrors); +} diff --git a/src/core/friendly_errors/stacktrace.js b/src/core/friendly_errors/stacktrace.js index fe6a1b5722..1777abac41 100644 --- a/src/core/friendly_errors/stacktrace.js +++ b/src/core/friendly_errors/stacktrace.js @@ -2,8 +2,6 @@ * @for p5 * @requires core */ -import p5 from '../main'; - // Borrow from stacktracejs https://github.com/stacktracejs/stacktrace.js with // minor modifications. The license for the same and the code is included below @@ -241,7 +239,14 @@ function ErrorStackParser() { // End borrow // wrapper exposing ErrorStackParser -p5._getErrorStackParser = function getErrorStackParser() { - return new ErrorStackParser(); -}; -export default p5; +function stacktrace(p5, fn){ + p5._getErrorStackParser = function getErrorStackParser() { + return new ErrorStackParser(); + }; +} + +export default stacktrace; + +if (typeof p5 !== 'undefined') { + stacktrace(p5, p5.prototype); +} From f35818cf9ea189eedc7314b2f5f614576ea7e2f1 Mon Sep 17 00:00:00 2001 From: limzykenneth Date: Wed, 18 Dec 2024 19:55:31 +0000 Subject: [PATCH 3/7] Refactor global init and fix FES param check not have documentation entry --- src/app.js | 4 +++- src/core/constants.js | 4 ++-- src/core/friendly_errors/param_validator.js | 3 +++ src/core/init.js | 8 +++----- src/shape/vertex.js | 2 +- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/app.js b/src/app.js index 27a98bcb5e..8b5579f252 100644 --- a/src/app.js +++ b/src/app.js @@ -61,6 +61,8 @@ webgl(p5); import type from './type' type(p5); -import './core/init'; +import { waitForDocumentReady, waitingForTranslator, _globalInit } from './core/init'; +Promise.all([waitForDocumentReady(), waitingForTranslator]).then(_globalInit); export default p5; + diff --git a/src/core/constants.js b/src/core/constants.js index 60d0d1ba09..0885ab3e48 100644 --- a/src/core/constants.js +++ b/src/core/constants.js @@ -45,7 +45,7 @@ export const P2DHDR = 'p2d-hdr'; * @property {WEBGL} WEBGL * @final */ -export const WEBGL = Symbol('webgl'); +export const WEBGL = 'webgl'; /** * One of the two possible values of a WebGL canvas (either WEBGL or WEBGL2), * which can be used to determine what capabilities the rendering environment @@ -54,7 +54,7 @@ export const WEBGL = Symbol('webgl'); * @property {WEBGL2} WEBGL2 * @final */ -export const WEBGL2 = Symbol('webgl2'); +export const WEBGL2 = 'webgl2'; // ENVIRONMENT /** diff --git a/src/core/friendly_errors/param_validator.js b/src/core/friendly_errors/param_validator.js index a81b1d1409..45d976c937 100644 --- a/src/core/friendly_errors/param_validator.js +++ b/src/core/friendly_errors/param_validator.js @@ -131,6 +131,8 @@ function validateParams(p5, fn, lifecycles) { const { funcName, funcClass } = extractFuncNameAndClass(func); let funcInfo = dataDoc[funcClass][funcName]; + if(!funcInfo) return; + let overloads = []; if (funcInfo.hasOwnProperty('overloads')) { overloads = funcInfo.overloads; @@ -466,6 +468,7 @@ function validateParams(p5, fn, lifecycles) { let funcSchemas = schemaRegistry.get(func); if (!funcSchemas) { funcSchemas = fn.generateZodSchemasForFunc(func); + if (!funcSchemas) return; schemaRegistry.set(func, funcSchemas); } diff --git a/src/core/init.js b/src/core/init.js index 88922bbd71..d6ac049bb2 100644 --- a/src/core/init.js +++ b/src/core/init.js @@ -12,7 +12,7 @@ import { initialize as initTranslator } from './internationalization'; * @private * @return {Undefined} */ -const _globalInit = () => { +export const _globalInit = () => { // Could have been any property defined within the p5 constructor. // If that property is already a part of the global object, // this code has already run before, likely due to a duplicate import @@ -37,7 +37,7 @@ const _globalInit = () => { }; // make a promise that resolves when the document is ready -const waitForDocumentReady = () => +export const waitForDocumentReady = () => new Promise((resolve, reject) => { // if the page is ready, initialize p5 immediately if (document.readyState === 'complete') { @@ -50,8 +50,6 @@ const waitForDocumentReady = () => }); // only load translations if we're using the full, un-minified library -const waitingForTranslator = +export const waitingForTranslator = typeof IS_MINIFIED === 'undefined' ? initTranslator() : Promise.resolve(); - -Promise.all([waitForDocumentReady(), waitingForTranslator]).then(_globalInit); diff --git a/src/shape/vertex.js b/src/shape/vertex.js index 6252d0677a..71ba437bb3 100644 --- a/src/shape/vertex.js +++ b/src/shape/vertex.js @@ -1854,7 +1854,7 @@ function vertex(p5, fn){ */ fn.vertexProperty = function(attributeName, data){ // this._assert3d('vertexProperty'); - p5._validateParameters('vertexProperty', arguments); + // p5._validateParameters('vertexProperty', arguments); this._renderer.vertexProperty(attributeName, data); }; } From adbed701b119fc3f34a68b95929089f884877b96 Mon Sep 17 00:00:00 2001 From: limzykenneth Date: Thu, 19 Dec 2024 21:11:21 +0000 Subject: [PATCH 4/7] Catch case where color constructor is not called correctly --- src/color/p5.Color.js | 3 +++ src/core/friendly_errors/param_validator.js | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/color/p5.Color.js b/src/color/p5.Color.js index 0df96a4abd..8f575fbaef 100644 --- a/src/color/p5.Color.js +++ b/src/color/p5.Color.js @@ -107,6 +107,9 @@ class Color { }else if(vals.length === 1){ mappedVals = Color.mapColorRange([vals[0], vals[0], vals[0]], this.mode, colorMaxes); mappedVals.push(1); + }else{ + console.error('Invalid color'); + return; } }else{ mappedVals = vals; diff --git a/src/core/friendly_errors/param_validator.js b/src/core/friendly_errors/param_validator.js index 45d976c937..db0bde6aa1 100644 --- a/src/core/friendly_errors/param_validator.js +++ b/src/core/friendly_errors/param_validator.js @@ -496,8 +496,8 @@ function validateParams(p5, fn, lifecycles) { for(const f in this){ if(!excludes.includes(f) && !f.startsWith('_') && typeof this[f] === 'function'){ const copy = this[f]; - this[f] = (...args) => { - // if (f === 'arc') this.validate(f, args); + + this[f] = function(...args) { this.validate(f, args); return copy.call(this, ...args); }; From 114323feb5e820173ad9bc35ec98866e76ab4063 Mon Sep 17 00:00:00 2001 From: limzykenneth Date: Thu, 19 Dec 2024 22:24:11 +0000 Subject: [PATCH 5/7] Improve message printing for FES and color --- src/color/p5.Color.js | 5 ++--- src/core/friendly_errors/fes_core.js | 2 +- src/core/friendly_errors/param_validator.js | 8 ++++---- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/color/p5.Color.js b/src/color/p5.Color.js index 8f575fbaef..b3f0fe13d9 100644 --- a/src/color/p5.Color.js +++ b/src/color/p5.Color.js @@ -89,7 +89,7 @@ class Color { this._color = to(this._color, this._color.spaceId); }catch(err){ // TODO: Invalid color string - console.error('Invalid color string'); + throw new Error('Invalid color string'); } }else{ @@ -108,8 +108,7 @@ class Color { mappedVals = Color.mapColorRange([vals[0], vals[0], vals[0]], this.mode, colorMaxes); mappedVals.push(1); }else{ - console.error('Invalid color'); - return; + throw new Error('Invalid color'); } }else{ mappedVals = vals; diff --git a/src/core/friendly_errors/fes_core.js b/src/core/friendly_errors/fes_core.js index 9e6ca11432..00ffa5ed66 100644 --- a/src/core/friendly_errors/fes_core.js +++ b/src/core/friendly_errors/fes_core.js @@ -553,7 +553,7 @@ function fesCore(p5, fn){ // get the function just above the topmost frame in the friendlyStack. // i.e the name of the library function called from user's code - const func = stacktrace[friendlyStack[0].frameIndex - 1].functionName + const func = stacktrace[friendlyStack[0].frameIndex - 2].functionName .split('.') .slice(-1)[0]; diff --git a/src/core/friendly_errors/param_validator.js b/src/core/friendly_errors/param_validator.js index db0bde6aa1..975c5eab95 100644 --- a/src/core/friendly_errors/param_validator.js +++ b/src/core/friendly_errors/param_validator.js @@ -331,7 +331,7 @@ function validateParams(p5, fn, lifecycles) { * @returns {String} The friendly error message. */ fn.friendlyParamError = function (zodErrorObj, func) { - let message; + let message = '🌸 p5.js says: '; // The `zodErrorObj` might contain multiple errors of equal importance // (after scoring the schema closeness in `findClosestSchema`). Here, we // always print the first error so that user can work through the errors @@ -392,16 +392,16 @@ function validateParams(p5, fn, lifecycles) { } case 'too_small': { const minArgs = currentError.minimum; - message = `Expected at least ${minArgs} argument${minArgs > 1 ? 's' : ''}, but received fewer`; + message += `Expected at least ${minArgs} argument${minArgs > 1 ? 's' : ''}, but received fewer`; break; } case 'invalid_type': { - message = buildTypeMismatchMessage(currentError.received, currentError.expected, currentError.path.join('.')); + message += buildTypeMismatchMessage(currentError.received, currentError.expected, currentError.path.join('.')); break; } case 'too_big': { const maxArgs = currentError.maximum; - message = `Expected at most ${maxArgs} argument${maxArgs > 1 ? 's' : ''}, but received more`; + message += `Expected at most ${maxArgs} argument${maxArgs > 1 ? 's' : ''}, but received more`; break; } default: { From 2d00e9eb3867032d99949620f88a6eb0b8d34255 Mon Sep 17 00:00:00 2001 From: limzykenneth Date: Sat, 28 Dec 2024 20:49:43 +0000 Subject: [PATCH 6/7] Set hard coded createCanvas parameter --- docs/parameterData.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/parameterData.json b/docs/parameterData.json index 545de2f5a7..b9fbd6670e 100644 --- a/docs/parameterData.json +++ b/docs/parameterData.json @@ -374,7 +374,7 @@ [ "Number?", "Number?", - "P2D|WEBGL?", + "String?", "HTMLCanvasElement?" ], [ From e4eb7c414d9ed1b8cf63d30fa3afcb24242295ec Mon Sep 17 00:00:00 2001 From: limzykenneth Date: Sat, 28 Dec 2024 20:50:16 +0000 Subject: [PATCH 7/7] Clean up --- src/core/rendering.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/rendering.js b/src/core/rendering.js index 58bd7b5d3f..810ce3bc32 100644 --- a/src/core/rendering.js +++ b/src/core/rendering.js @@ -9,8 +9,6 @@ import { Framebuffer } from '../webgl/p5.Framebuffer'; let renderers; function rendering(p5, fn){ - let defaultId = 'defaultCanvas0'; // this gets set again in createCanvas - const defaultClass = 'p5Canvas'; // Extend additional renderers object to p5 class, new renderer can be similarly attached renderers = p5.renderers = {};