First commit
This commit is contained in:
+83
@@ -0,0 +1,83 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = deleteUnknownAutoBindMethods;
|
||||
function shouldDeleteClassicInstanceMethod(component, name) {
|
||||
if (component.__reactAutoBindMap && component.__reactAutoBindMap.hasOwnProperty(name)) {
|
||||
// It's a known autobound function, keep it
|
||||
return false;
|
||||
}
|
||||
|
||||
if (component.__reactAutoBindPairs && component.__reactAutoBindPairs.indexOf(name) >= 0) {
|
||||
// It's a known autobound function, keep it
|
||||
return false;
|
||||
}
|
||||
|
||||
if (component[name].__reactBoundArguments !== null) {
|
||||
// It's a function bound to specific args, keep it
|
||||
return false;
|
||||
}
|
||||
|
||||
// It's a cached bound method for a function
|
||||
// that was deleted by user, so we delete it from component.
|
||||
return true;
|
||||
}
|
||||
|
||||
function shouldDeleteModernInstanceMethod(component, name) {
|
||||
var prototype = component.constructor.prototype;
|
||||
|
||||
var prototypeDescriptor = Object.getOwnPropertyDescriptor(prototype, name);
|
||||
|
||||
if (!prototypeDescriptor || !prototypeDescriptor.get) {
|
||||
// This is definitely not an autobinding getter
|
||||
return false;
|
||||
}
|
||||
|
||||
if (prototypeDescriptor.get().length !== component[name].length) {
|
||||
// The length doesn't match, bail out
|
||||
return false;
|
||||
}
|
||||
|
||||
// This seems like a method bound using an autobinding getter on the prototype
|
||||
// Hopefully we won't run into too many false positives.
|
||||
return true;
|
||||
}
|
||||
|
||||
function shouldDeleteInstanceMethod(component, name) {
|
||||
var descriptor = Object.getOwnPropertyDescriptor(component, name);
|
||||
if (typeof descriptor.value !== 'function') {
|
||||
// Not a function, or something fancy: bail out
|
||||
return;
|
||||
}
|
||||
|
||||
if (component.__reactAutoBindMap || component.__reactAutoBindPairs) {
|
||||
// Classic
|
||||
return shouldDeleteClassicInstanceMethod(component, name);
|
||||
} else {
|
||||
// Modern
|
||||
return shouldDeleteModernInstanceMethod(component, name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes autobound methods from the instance.
|
||||
*
|
||||
* For classic React classes, we only delete the methods that no longer exist in map.
|
||||
* This means the user actually deleted them in code.
|
||||
*
|
||||
* For modern classes, we delete methods that exist on prototype with the same length,
|
||||
* and which have getters on prototype, but are normal values on the instance.
|
||||
* This is usually an indication that an autobinding decorator is being used,
|
||||
* and the getter will re-generate the memoized handler on next access.
|
||||
*/
|
||||
function deleteUnknownAutoBindMethods(component) {
|
||||
var names = Object.getOwnPropertyNames(component);
|
||||
|
||||
names.forEach(function (name) {
|
||||
if (shouldDeleteInstanceMethod(component, name)) {
|
||||
delete component[name];
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user