UNPKG

2.41 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = deleteUnknownAutoBindMethods;
7function shouldDeleteClassicInstanceMethod(component, name) {
8 if (component.__reactAutoBindMap.hasOwnProperty(name)) {
9 // It's a known autobound function, keep it
10 return false;
11 }
12
13 if (component[name].__reactBoundArguments !== null) {
14 // It's a function bound to specific args, keep it
15 return false;
16 }
17
18 // It's a cached bound method for a function
19 // that was deleted by user, so we delete it from component.
20 return true;
21}
22
23function shouldDeleteModernInstanceMethod(component, name) {
24 const prototype = component.constructor.prototype;
25
26 const prototypeDescriptor = Object.getOwnPropertyDescriptor(prototype, name);
27
28 if (!prototypeDescriptor || !prototypeDescriptor.get) {
29 // This is definitely not an autobinding getter
30 return false;
31 }
32
33 if (prototypeDescriptor.get().length !== component[name].length) {
34 // The length doesn't match, bail out
35 return false;
36 }
37
38 // This seems like a method bound using an autobinding getter on the prototype
39 // Hopefully we won't run into too many false positives.
40 return true;
41}
42
43function shouldDeleteInstanceMethod(component, name) {
44 const descriptor = Object.getOwnPropertyDescriptor(component, name);
45 if (typeof descriptor.value !== 'function') {
46 // Not a function, or something fancy: bail out
47 return;
48 }
49
50 if (component.__reactAutoBindMap) {
51 // Classic
52 return shouldDeleteClassicInstanceMethod(component, name);
53 } else {
54 // Modern
55 return shouldDeleteModernInstanceMethod(component, name);
56 }
57}
58
59/**
60 * Deletes autobound methods from the instance.
61 *
62 * For classic React classes, we only delete the methods that no longer exist in map.
63 * This means the user actually deleted them in code.
64 *
65 * For modern classes, we delete methods that exist on prototype with the same length,
66 * and which have getters on prototype, but are normal values on the instance.
67 * This is usually an indication that an autobinding decorator is being used,
68 * and the getter will re-generate the memoized handler on next access.
69 */
70function deleteUnknownAutoBindMethods(component) {
71 const names = Object.getOwnPropertyNames(component);
72
73 names.forEach(function (name) {
74 if (shouldDeleteInstanceMethod(component, name)) {
75 delete component[name];
76 }
77 });
78}
\No newline at end of file