Skip to content

Commit b7ecbac

Browse files
committed
Apply function decoration just before class contruction
1 parent 419574a commit b7ecbac

File tree

4 files changed

+617
-82
lines changed

4 files changed

+617
-82
lines changed

src/core/friendly_errors/param_validator.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,7 @@ function validateParams(p5, fn, lifecycles) {
579579
if (!p5.disableFriendlyErrors && !p5.disableParameterValidator) {
580580
validate(name, args);
581581
}
582-
return p5.prototype[name].apply(this, args);
582+
return target.call(this, ...args);
583583
};
584584
}
585585
);

src/core/main.js

Lines changed: 47 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -77,24 +77,6 @@ class p5 {
7777
// ensure correct reporting of window dimensions
7878
this._updateWindowSize();
7979

80-
// Apply addon defined decorations
81-
for (const [patternArray, decoration] of p5.decorations) {
82-
for(const member in p5.prototype) {
83-
// Member must be a function
84-
if (typeof p5.prototype[member] !== 'function') continue;
85-
86-
if (!patternArray.some(pattern => {
87-
if (typeof pattern === 'string') {
88-
return pattern === member;
89-
} else if (pattern instanceof RegExp) {
90-
return pattern.test(member);
91-
}
92-
})) continue;
93-
94-
DecoratedP5.prototype[member] = decoration.call(this, p5.prototype[member], member);
95-
}
96-
}
97-
9880
const bindGlobal = createBindGlobal(this);
9981
// If the user has created a global setup or draw function,
10082
// assume "global" mode and make everything global (i.e. on the window)
@@ -422,39 +404,20 @@ class p5 {
422404
}
423405
}
424406

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-
437407
// Global helper function for binding properties to window in global mode
438408
function createBindGlobal(instance) {
439409
return function bindGlobal(property) {
440410
if (property === 'constructor') return;
441411

442-
// Common setter for all property types
443-
const createSetter = () => newValue => {
444-
Object.defineProperty(window, property, {
445-
configurable: true,
446-
enumerable: true,
447-
value: newValue,
448-
writable: true
449-
});
450-
if (!p5.disableFriendlyErrors) {
451-
console.log(`You just changed the value of "${property}", which was a p5 global value. This could cause problems later if you're not careful.`);
452-
}
453-
};
454-
455412
// Check if this property has a getter on the instance or prototype
456-
const instanceDescriptor = Object.getOwnPropertyDescriptor(instance, property);
457-
const prototypeDescriptor = Object.getOwnPropertyDescriptor(p5.prototype, property);
413+
const instanceDescriptor = Object.getOwnPropertyDescriptor(
414+
instance,
415+
property
416+
);
417+
const prototypeDescriptor = Object.getOwnPropertyDescriptor(
418+
p5.prototype,
419+
property
420+
);
458421
const hasGetter = (instanceDescriptor && instanceDescriptor.get) ||
459422
(prototypeDescriptor && prototypeDescriptor.get);
460423

@@ -479,40 +442,18 @@ function createBindGlobal(instance) {
479442
if (isPrototypeFunction) {
480443
// For regular functions, cache the bound function
481444
const boundFunction = p5.prototype[property].bind(instance);
482-
if (p5.disableFriendlyErrors) {
483-
Object.defineProperty(window, property, {
484-
configurable: true,
485-
enumerable: true,
486-
value: boundFunction
487-
});
488-
} else {
489-
Object.defineProperty(window, property, {
490-
configurable: true,
491-
enumerable: true,
492-
get() {
493-
return boundFunction;
494-
},
495-
set: createSetter()
496-
});
497-
}
445+
Object.defineProperty(window, property, {
446+
configurable: true,
447+
enumerable: true,
448+
value: boundFunction
449+
});
498450
} else if (isConstant) {
499451
// For constants, cache the value directly
500-
if (p5.disableFriendlyErrors) {
501-
Object.defineProperty(window, property, {
502-
configurable: true,
503-
enumerable: true,
504-
value: constantValue
505-
});
506-
} else {
507-
Object.defineProperty(window, property, {
508-
configurable: true,
509-
enumerable: true,
510-
get() {
511-
return constantValue;
512-
},
513-
set: createSetter()
514-
});
515-
}
452+
Object.defineProperty(window, property, {
453+
configurable: true,
454+
enumerable: true,
455+
value: constantValue
456+
});
516457
} else if (hasGetter || !isPrototypeFunction) {
517458
// For properties with getters or non-function properties, use lazy optimization
518459
// On first access, determine the type and optimize subsequent accesses
@@ -547,8 +488,7 @@ function createBindGlobal(instance) {
547488
// Optimized non-function path
548489
return currentValue;
549490
}
550-
},
551-
set: createSetter()
491+
}
552492
});
553493
}
554494
};
@@ -804,4 +744,31 @@ p5.registerAddon(renderer);
804744
p5.registerAddon(renderer2D);
805745
p5.registerAddon(graphics);
806746

807-
export default DecoratedP5;
747+
const p5Proxy = new Proxy(p5, {
748+
construct(target, args){
749+
if(p5.decorations.size > 0){
750+
// Apply addon defined decorations
751+
for (const [patternArray, decoration] of p5.decorations) {
752+
for(const member in p5.prototype) {
753+
// Member must be a function
754+
if (typeof p5.prototype[member] !== 'function') continue;
755+
756+
if (!patternArray.some(pattern => {
757+
if (typeof pattern === 'string') {
758+
return pattern === member;
759+
} else if (pattern instanceof RegExp) {
760+
return pattern.test(member);
761+
}
762+
})) continue;
763+
764+
p5.prototype[member] = decoration(p5.prototype[member], member);
765+
}
766+
}
767+
768+
p5.decorations.clear();
769+
}
770+
return new target(...args);
771+
}
772+
});
773+
774+
export default p5Proxy;

0 commit comments

Comments
 (0)