/
make-exports-hot.js
113 lines (85 loc) · 2.37 KB
/
make-exports-hot.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
'use strict';
var warn = require('../safe-warn')
// These functions are modified copies from:
// https://github.com/gaearon/react-hot-loader
module.exports = function makeExportsHot(m, React, id, makeHot, ignored) {
if (isReactElementish(m.exports)) {
// React elements are never valid React classes
return false;
}
var freshExports = m.exports,
exportsReactClass = isReactClassish(m.exports, React),
foundReactClasses = false;
if (exportsReactClass && !contains(ignored, m.exports)) {
m.exports = makeHot(m.exports, id);
foundReactClasses = true;
}
for (var key in m.exports) {
if (!Object.prototype.hasOwnProperty.call(freshExports, key)) {
continue;
}
if (exportsReactClass && key === 'type') {
// React 0.12 also puts classes under `type` property for compat.
// Skip to avoid updating twice.
continue;
}
if (!isReactClassish(freshExports[key], React)) {
continue;
}
if (Object.getOwnPropertyDescriptor(m.exports, key).writable) {
if (!contains(ignored, freshExports[key])) {
m.exports[key] = makeHot(freshExports[key], id + '.' + key);
foundReactClasses = true;
}
} else {
warn('Can\'t make class ' + key + ' hot reloadable due to being read-only.');
}
}
return foundReactClasses;
}
function contains(col, val) {
for (var i = 0 ; i < col.length ; i++) {
if (col[i] === val) return true
}
return false
}
function hasRender(Class) {
var prototype = Class.prototype;
if (!prototype) {
return false;
}
return typeof prototype.render === 'function';
}
function descendsFromReactComponent(Class, React) {
if (!React.Component) {
return false;
}
var Base = Object.getPrototypeOf(Class);
while (Base) {
if (Base === React.Component) {
return true;
}
Base = Object.getPrototypeOf(Base);
}
return false;
}
function isReactClassish(Class, React) {
if (typeof Class !== 'function') {
return false;
}
// React 0.13
if (hasRender(Class) || descendsFromReactComponent(Class, React)) {
return true;
}
// React 0.12 and earlier
if (Class.type && hasRender(Class.type)) {
return true;
}
return false;
}
function isReactElementish(obj) {
if (!obj) {
return false;
}
return Object.prototype.toString.call(obj.props) === '[object Object]' && isReactClassish(obj.type);
}