83 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			83 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'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];
 | 
						|
    }
 | 
						|
  });
 | 
						|
} |