Skip to content

Commit 419574a

Browse files
committed
Add decorators to a subclass instead
1 parent ad206b7 commit 419574a

File tree

4 files changed

+50
-39
lines changed

4 files changed

+50
-39
lines changed

src/core/friendly_errors/param_validator.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -570,14 +570,16 @@ function validateParams(p5, fn, lifecycles) {
570570
}
571571
};
572572

573+
fn._validate = validate; // For unit tests
574+
573575
p5.decorateHelper(
574576
/^(?!_).+$/,
575577
function(target, name){
576578
return function(...args){
577-
if(!p5.disableFriendlyErrors && !p5.disableParameterValidator) {
579+
if (!p5.disableFriendlyErrors && !p5.disableParameterValidator) {
578580
validate(name, args);
579581
}
580-
return target(...args);
582+
return p5.prototype[name].apply(this, args);
581583
};
582584
}
583585
);

src/core/main.js

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -78,25 +78,20 @@ class p5 {
7878
this._updateWindowSize();
7979

8080
// Apply addon defined decorations
81-
p5.prototype.__originalMethods = p5.prototype.__originalMethods || {};
82-
for(const [patternArray, decoration] of p5.decorations){
83-
for(const member in p5.prototype){
81+
for (const [patternArray, decoration] of p5.decorations) {
82+
for(const member in p5.prototype) {
8483
// Member must be a function
85-
if(typeof p5.prototype[member] !== 'function') continue;
84+
if (typeof p5.prototype[member] !== 'function') continue;
8685

87-
if(!patternArray.some(pattern => {
88-
if(typeof pattern === 'string'){
86+
if (!patternArray.some(pattern => {
87+
if (typeof pattern === 'string') {
8988
return pattern === member;
90-
}else if(pattern instanceof RegExp){
89+
} else if (pattern instanceof RegExp) {
9190
return pattern.test(member);
9291
}
9392
})) continue;
9493

95-
// Store a copy of the original, unbound prototype method so that if we make a new p5 instance
96-
// later, we don't double-, triple-, etc bind the function
97-
p5.prototype.__originalMethods[member] = p5.prototype.__originalMethods[member] || p5.prototype[member];
98-
const copy = p5.prototype.__originalMethods[member].bind(this);
99-
p5.prototype[member] = decoration.call(this, copy, member);
94+
DecoratedP5.prototype[member] = decoration.call(this, p5.prototype[member], member);
10095
}
10196
}
10297

@@ -181,7 +176,7 @@ class p5 {
181176
static decorations = new Map();
182177
static decorateHelper(pattern, decoration){
183178
let patternArray = pattern;
184-
if(!Array.isArray(pattern)) patternArray = [pattern];
179+
if (!Array.isArray(pattern)) patternArray = [pattern];
185180
p5.decorations.set(patternArray, decoration);
186181
}
187182

@@ -427,6 +422,18 @@ class p5 {
427422
}
428423
}
429424

425+
class _DecoratedP5 extends p5 {
426+
static registerAddon(addon) {
427+
p5.registerAddon(addon);
428+
}
429+
}
430+
const DecoratedP5 = new Proxy(_DecoratedP5, {
431+
set(target, prop, newValue) {
432+
p5[prop] = newValue;
433+
return true;
434+
}
435+
});
436+
430437
// Global helper function for binding properties to window in global mode
431438
function createBindGlobal(instance) {
432439
return function bindGlobal(property) {
@@ -797,4 +804,4 @@ p5.registerAddon(renderer);
797804
p5.registerAddon(renderer2D);
798805
p5.registerAddon(graphics);
799806

800-
export default p5;
807+
export default DecoratedP5;

src/webgl/p5.Framebuffer.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1679,6 +1679,7 @@ function framebuffer(p5, fn){
16791679
* object.
16801680
* @param {Object} [settings] configuration options.
16811681
*/
1682+
debugger
16821683
p5.Framebuffer = Framebuffer;
16831684

16841685
/**

test/unit/core/param_errors.js

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ suite('Validate Params', function () {
2828
Graphics: function() {
2929
return 'mock p5.Graphics';
3030
},
31-
_error: () => {}
31+
_error: () => {},
32+
decorateHelper: () => {},
3233
};
3334
const mockP5Prototype = {};
3435

@@ -48,7 +49,7 @@ suite('Validate Params', function () {
4849
];
4950

5051
validInputs.forEach(({ input }) => {
51-
const result = mockP5Prototype.validate('saturation', input);
52+
const result = mockP5Prototype._validate('saturation', input);
5253
assert.isTrue(result.success);
5354
});
5455
});
@@ -62,7 +63,7 @@ suite('Validate Params', function () {
6263
];
6364

6465
invalidInputs.forEach(({ input }) => {
65-
const result = mockP5Prototype.validate('p5.saturation', input);
66+
const result = mockP5Prototype._validate('p5.saturation', input);
6667
assert.isTrue(result.error.startsWith('🌸 p5.js says: Expected Color or array or string at the first parameter, but received'));
6768
});
6869
});
@@ -76,7 +77,7 @@ suite('Validate Params', function () {
7677

7778
validInputs.forEach(({ name, input }) => {
7879
test(`blendMode(): ${name}`, () => {
79-
const result = mockP5Prototype.validate('p5.blendMode', [input]);
80+
const result = mockP5Prototype._validate('p5.blendMode', [input]);
8081
assert.isTrue(result.success);
8182
});
8283
});
@@ -89,7 +90,7 @@ suite('Validate Params', function () {
8990

9091
invalidInputs.forEach(({ name, input }) => {
9192
test(`blendMode(): ${name}`, () => {
92-
const result = mockP5Prototype.validate('p5.blendMode', [input]);
93+
const result = mockP5Prototype._validate('p5.blendMode', [input]);
9394
const expectedError = '🌸 p5.js says: Expected constant (please refer to documentation for allowed values) at the first parameter, but received ' + input + ' in p5.blendMode().';
9495
assert.equal(result.error, expectedError);
9596
});
@@ -103,7 +104,7 @@ suite('Validate Params', function () {
103104
];
104105
validInputs.forEach(({ name, input }) => {
105106
test(`arc(): ${name}`, () => {
106-
const result = mockP5Prototype.validate('p5.arc', input);
107+
const result = mockP5Prototype._validate('p5.arc', input);
107108
assert.isTrue(result.success);
108109
});
109110
});
@@ -118,15 +119,15 @@ suite('Validate Params', function () {
118119

119120
invalidInputs.forEach(({ name, input, msg }) => {
120121
test(`arc(): ${name}`, () => {
121-
const result = mockP5Prototype.validate('p5.arc', input);
122+
const result = mockP5Prototype._validate('p5.arc', input);
122123
assert.equal(result.error, msg);
123124
});
124125
});
125126
});
126127

127128
suite('validateParams: promise where no promise is expected', function () {
128129
test('image(): promise for first argument', function () {
129-
const result = mockP5Prototype.validate('p5.image', [Promise.resolve(), 0, 0]);
130+
const result = mockP5Prototype._validate('p5.image', [Promise.resolve(), 0, 0]);
130131
console.log(result);
131132
assert.equal(
132133
result.error,
@@ -137,7 +138,7 @@ suite('Validate Params', function () {
137138

138139
suite('validateParams: class, multi-types + optional numbers', function () {
139140
test('ambientLight(): no firendly-err-msg', function () {
140-
const result = mockP5Prototype.validate('p5.ambientLight', [new mockP5.Color()]);
141+
const result = mockP5Prototype._validate('p5.ambientLight', [new mockP5.Color()]);
141142
assert.isTrue(result.success);
142143
});
143144
});
@@ -155,7 +156,7 @@ suite('Validate Params', function () {
155156

156157
invalidInputs.forEach(({ name, input, fn, msg }) => {
157158
test(`${fn}(): ${name}`, () => {
158-
const result = mockP5Prototype.validate(`p5.${fn}`, input);
159+
const result = mockP5Prototype._validate(`p5.${fn}`, input);
159160
assert.equal(result.error, msg);
160161
});
161162
});
@@ -173,7 +174,7 @@ suite('Validate Params', function () {
173174

174175
invalidInputs.forEach(({ fn, name, input, msg }) => {
175176
test(`${fn}(): ${name}`, () => {
176-
const result = mockP5Prototype.validate(`p5.${fn}`, input);
177+
const result = mockP5Prototype._validate(`p5.${fn}`, input);
177178
assert.equal(result.error, msg);
178179
});
179180
});
@@ -187,7 +188,7 @@ suite('Validate Params', function () {
187188
];
188189
validInputs.forEach(({ name, input }) => {
189190
test(`color(): ${name}`, () => {
190-
const result = mockP5Prototype.validate('p5.color', input);
191+
const result = mockP5Prototype._validate('p5.color', input);
191192
assert.isTrue(result.success);
192193
});
193194
});
@@ -201,7 +202,7 @@ suite('Validate Params', function () {
201202

202203
invalidInputs.forEach(({ name, input, msg }) => {
203204
test(`color(): ${name}`, () => {
204-
const result = mockP5Prototype.validate('p5.color', input);
205+
const result = mockP5Prototype._validate('p5.color', input);
205206

206207
assert.equal(result.error, msg);
207208
});
@@ -216,13 +217,13 @@ suite('Validate Params', function () {
216217
];
217218
validInputs.forEach(({ name, input }) => {
218219
test(`${name}`, function () {
219-
const result = mockP5Prototype.validate('p5.set', input);
220+
const result = mockP5Prototype._validate('p5.set', input);
220221
assert.isTrue(result.success);
221222
});
222223
});
223224

224225
test('set() with Boolean (invalid)', function () {
225-
const result = mockP5Prototype.validate('p5.set', [0, 0, true]);
226+
const result = mockP5Prototype._validate('p5.set', [0, 0, true]);
226227
assert.equal(result.error, '🌸 p5.js says: Expected number or array or object at the third parameter, but received boolean in p5.set().');
227228
});
228229
});
@@ -238,7 +239,7 @@ suite('Validate Params', function () {
238239

239240
testCases.forEach(({ fn, name, input }) => {
240241
test(`${fn}(): ${name}`, function () {
241-
const result = mockP5Prototype.validate(fn, input);
242+
const result = mockP5Prototype._validate(fn, input);
242243
assert.isTrue(result.success);
243244
});
244245
});
@@ -251,31 +252,31 @@ suite('Validate Params', function () {
251252
[new mockP5.Color(), 0.8],
252253
[new mockP5.Color(), 0.5]
253254
];
254-
const result = mockP5Prototype.validate('p5.paletteLerp', [colorStops, 0.5]);
255+
const result = mockP5Prototype._validate('p5.paletteLerp', [colorStops, 0.5]);
255256
assert.isTrue(result.success);
256257
});
257258
});
258259

259260
suite('validateParams: rest arguments', function () {
260261
test('createVector(): works with no args', function() {
261-
const result = mockP5Prototype.validate('p5.createVector', []);
262+
const result = mockP5Prototype._validate('p5.createVector', []);
262263
assert.isTrue(result.success);
263264
});
264265
test('createVector(): works with one number', function() {
265-
const result = mockP5Prototype.validate('p5.createVector', [1]);
266+
const result = mockP5Prototype._validate('p5.createVector', [1]);
266267
assert.isTrue(result.success);
267268
});
268269
test('createVector(): works with many numbers', function() {
269-
const result = mockP5Prototype.validate('p5.createVector', [1, 2, 3, 4]);
270+
const result = mockP5Prototype._validate('p5.createVector', [1, 2, 3, 4]);
270271
assert.isTrue(result.success);
271272
});
272273
test('createVector(): fails with a non-number', function() {
273-
const result = mockP5Prototype.validate('p5.createVector', ['1']);
274+
const result = mockP5Prototype._validate('p5.createVector', ['1']);
274275
assert.isFalse(result.success);
275276
});
276277
test('createVector(): fails with any non-number', function() {
277-
const result = mockP5Prototype.validate('p5.createVector', [1, 2, '3', 4]);
278+
const result = mockP5Prototype._validate('p5.createVector', [1, 2, '3', 4]);
278279
assert.isFalse(result.success);
279280
});
280281
});
281-
});
282+
});

0 commit comments

Comments
 (0)