@uniflowed/vite 0.0.0-alpha.1 → 0.0.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/driver.js +125 -17
- package/index.js +61 -6
- package/internal/config.js +13 -4
- package/internal/events.js +2 -0
- package/internal/flow-grammar-shim.js +241 -0
- package/internal/flow-keywords.js +505 -0
- package/internal/highlight.js +181 -0
- package/internal/refresh-runtime.js +221 -246
- package/internal/refresh.js +2 -0
- package/internal/routes.js +47 -6
- package/merge.js +87 -0
- package/package.json +9 -10
- package/bun-preload.js +0 -22
- package/internal/node-hooks.js +0 -111
- package/register.js +0 -11
- package/transform.js +0 -187
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// @noflow
|
|
2
|
+
//
|
|
1
3
|
/* global window */
|
|
2
4
|
/* eslint-disable eqeqeq, prefer-const, @typescript-eslint/no-empty-function */
|
|
3
5
|
|
|
@@ -8,276 +10,272 @@
|
|
|
8
10
|
* Some utils are appended at the bottom for HMR integration.
|
|
9
11
|
*/
|
|
10
12
|
|
|
11
|
-
const REACT_FORWARD_REF_TYPE = Symbol.for(
|
|
12
|
-
const REACT_MEMO_TYPE = Symbol.for(
|
|
13
|
+
const REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref");
|
|
14
|
+
const REACT_MEMO_TYPE = Symbol.for("react.memo");
|
|
13
15
|
|
|
14
16
|
// We never remove these associations.
|
|
15
17
|
// It's OK to reference families, but use WeakMap/Set for types.
|
|
16
|
-
let allFamiliesByID = new Map()
|
|
17
|
-
let allFamiliesByType = new WeakMap()
|
|
18
|
-
let allSignaturesByType = new WeakMap()
|
|
18
|
+
let allFamiliesByID = new Map();
|
|
19
|
+
let allFamiliesByType = new WeakMap();
|
|
20
|
+
let allSignaturesByType = new WeakMap();
|
|
19
21
|
|
|
20
22
|
// This WeakMap is read by React, so we only put families
|
|
21
23
|
// that have actually been edited here. This keeps checks fast.
|
|
22
|
-
const updatedFamiliesByType = new WeakMap()
|
|
24
|
+
const updatedFamiliesByType = new WeakMap();
|
|
23
25
|
|
|
24
26
|
// This is cleared on every performReactRefresh() call.
|
|
25
27
|
// It is an array of [Family, NextType] tuples.
|
|
26
|
-
let pendingUpdates = []
|
|
28
|
+
let pendingUpdates = [];
|
|
27
29
|
|
|
28
30
|
// This is injected by the renderer via DevTools global hook.
|
|
29
|
-
const helpersByRendererID = new Map()
|
|
31
|
+
const helpersByRendererID = new Map();
|
|
30
32
|
|
|
31
|
-
const helpersByRoot = new Map()
|
|
33
|
+
const helpersByRoot = new Map();
|
|
32
34
|
|
|
33
35
|
// We keep track of mounted roots so we can schedule updates.
|
|
34
|
-
const mountedRoots = new Set()
|
|
36
|
+
const mountedRoots = new Set();
|
|
35
37
|
// If a root captures an error, we remember it so we can retry on edit.
|
|
36
|
-
const failedRoots = new Set()
|
|
38
|
+
const failedRoots = new Set();
|
|
37
39
|
|
|
38
40
|
// We also remember the last element for every root.
|
|
39
41
|
// It needs to be weak because we do this even for roots that failed to mount.
|
|
40
42
|
// If there is no WeakMap, we won't attempt to do retrying.
|
|
41
|
-
let rootElements = new WeakMap()
|
|
42
|
-
let isPerformingRefresh = false
|
|
43
|
+
let rootElements = new WeakMap();
|
|
44
|
+
let isPerformingRefresh = false;
|
|
43
45
|
|
|
44
46
|
function computeFullKey(signature) {
|
|
45
47
|
if (signature.fullKey !== null) {
|
|
46
|
-
return signature.fullKey
|
|
48
|
+
return signature.fullKey;
|
|
47
49
|
}
|
|
48
50
|
|
|
49
|
-
let fullKey = signature.ownKey
|
|
50
|
-
let hooks
|
|
51
|
+
let fullKey = signature.ownKey;
|
|
52
|
+
let hooks;
|
|
51
53
|
try {
|
|
52
|
-
hooks = signature.getCustomHooks()
|
|
54
|
+
hooks = signature.getCustomHooks();
|
|
53
55
|
} catch (err) {
|
|
54
56
|
// This can happen in an edge case, e.g. if expression like Foo.useSomething
|
|
55
57
|
// depends on Foo which is lazily initialized during rendering.
|
|
56
58
|
// In that case just assume we'll have to remount.
|
|
57
|
-
signature.forceReset = true
|
|
58
|
-
signature.fullKey = fullKey
|
|
59
|
-
return fullKey
|
|
59
|
+
signature.forceReset = true;
|
|
60
|
+
signature.fullKey = fullKey;
|
|
61
|
+
return fullKey;
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
for (let i = 0; i < hooks.length; i++) {
|
|
63
|
-
const hook = hooks[i]
|
|
64
|
-
if (typeof hook !==
|
|
65
|
+
const hook = hooks[i];
|
|
66
|
+
if (typeof hook !== "function") {
|
|
65
67
|
// Something's wrong. Assume we need to remount.
|
|
66
|
-
signature.forceReset = true
|
|
67
|
-
signature.fullKey = fullKey
|
|
68
|
-
return fullKey
|
|
68
|
+
signature.forceReset = true;
|
|
69
|
+
signature.fullKey = fullKey;
|
|
70
|
+
return fullKey;
|
|
69
71
|
}
|
|
70
|
-
const nestedHookSignature = allSignaturesByType.get(hook)
|
|
72
|
+
const nestedHookSignature = allSignaturesByType.get(hook);
|
|
71
73
|
if (nestedHookSignature === undefined) {
|
|
72
74
|
// No signature means Hook wasn't in the source code, e.g. in a library.
|
|
73
75
|
// We'll skip it because we can assume it won't change during this session.
|
|
74
|
-
continue
|
|
76
|
+
continue;
|
|
75
77
|
}
|
|
76
|
-
const nestedHookKey = computeFullKey(nestedHookSignature)
|
|
78
|
+
const nestedHookKey = computeFullKey(nestedHookSignature);
|
|
77
79
|
if (nestedHookSignature.forceReset) {
|
|
78
|
-
signature.forceReset = true
|
|
80
|
+
signature.forceReset = true;
|
|
79
81
|
}
|
|
80
|
-
fullKey +=
|
|
82
|
+
fullKey += "\n---\n" + nestedHookKey;
|
|
81
83
|
}
|
|
82
84
|
|
|
83
|
-
signature.fullKey = fullKey
|
|
84
|
-
return fullKey
|
|
85
|
+
signature.fullKey = fullKey;
|
|
86
|
+
return fullKey;
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
function haveEqualSignatures(prevType, nextType) {
|
|
88
|
-
const prevSignature = allSignaturesByType.get(prevType)
|
|
89
|
-
const nextSignature = allSignaturesByType.get(nextType)
|
|
90
|
+
const prevSignature = allSignaturesByType.get(prevType);
|
|
91
|
+
const nextSignature = allSignaturesByType.get(nextType);
|
|
90
92
|
|
|
91
93
|
if (prevSignature === undefined && nextSignature === undefined) {
|
|
92
|
-
return true
|
|
94
|
+
return true;
|
|
93
95
|
}
|
|
94
96
|
if (prevSignature === undefined || nextSignature === undefined) {
|
|
95
|
-
return false
|
|
97
|
+
return false;
|
|
96
98
|
}
|
|
97
99
|
if (computeFullKey(prevSignature) !== computeFullKey(nextSignature)) {
|
|
98
|
-
return false
|
|
100
|
+
return false;
|
|
99
101
|
}
|
|
100
102
|
if (nextSignature.forceReset) {
|
|
101
|
-
return false
|
|
103
|
+
return false;
|
|
102
104
|
}
|
|
103
105
|
|
|
104
|
-
return true
|
|
106
|
+
return true;
|
|
105
107
|
}
|
|
106
108
|
|
|
107
109
|
function isReactClass(type) {
|
|
108
|
-
return type.prototype && type.prototype.isReactComponent
|
|
110
|
+
return type.prototype && type.prototype.isReactComponent;
|
|
109
111
|
}
|
|
110
112
|
|
|
111
113
|
function canPreserveStateBetween(prevType, nextType) {
|
|
112
114
|
if (isReactClass(prevType) || isReactClass(nextType)) {
|
|
113
|
-
return false
|
|
115
|
+
return false;
|
|
114
116
|
}
|
|
115
117
|
if (haveEqualSignatures(prevType, nextType)) {
|
|
116
|
-
return true
|
|
118
|
+
return true;
|
|
117
119
|
}
|
|
118
|
-
return false
|
|
120
|
+
return false;
|
|
119
121
|
}
|
|
120
122
|
|
|
121
123
|
function resolveFamily(type) {
|
|
122
124
|
// Only check updated types to keep lookups fast.
|
|
123
|
-
return updatedFamiliesByType.get(type)
|
|
125
|
+
return updatedFamiliesByType.get(type);
|
|
124
126
|
}
|
|
125
127
|
|
|
126
128
|
// This is a safety mechanism to protect against rogue getters and Proxies.
|
|
127
129
|
function getProperty(object, property) {
|
|
128
130
|
try {
|
|
129
|
-
return object[property]
|
|
131
|
+
return object[property];
|
|
130
132
|
} catch (err) {
|
|
131
133
|
// Intentionally ignore.
|
|
132
|
-
return undefined
|
|
134
|
+
return undefined;
|
|
133
135
|
}
|
|
134
136
|
}
|
|
135
137
|
|
|
136
138
|
function performReactRefresh() {
|
|
137
139
|
if (pendingUpdates.length === 0) {
|
|
138
|
-
return null
|
|
140
|
+
return null;
|
|
139
141
|
}
|
|
140
142
|
if (isPerformingRefresh) {
|
|
141
|
-
return null
|
|
143
|
+
return null;
|
|
142
144
|
}
|
|
143
145
|
|
|
144
|
-
isPerformingRefresh = true
|
|
146
|
+
isPerformingRefresh = true;
|
|
145
147
|
try {
|
|
146
|
-
const staleFamilies = new Set()
|
|
147
|
-
const updatedFamilies = new Set()
|
|
148
|
+
const staleFamilies = new Set();
|
|
149
|
+
const updatedFamilies = new Set();
|
|
148
150
|
|
|
149
|
-
const updates = pendingUpdates
|
|
150
|
-
pendingUpdates = []
|
|
151
|
+
const updates = pendingUpdates;
|
|
152
|
+
pendingUpdates = [];
|
|
151
153
|
updates.forEach(([family, nextType]) => {
|
|
152
154
|
// Now that we got a real edit, we can create associations
|
|
153
155
|
// that will be read by the React reconciler.
|
|
154
|
-
const prevType = family.current
|
|
155
|
-
updatedFamiliesByType.set(prevType, family)
|
|
156
|
-
updatedFamiliesByType.set(nextType, family)
|
|
157
|
-
family.current = nextType
|
|
156
|
+
const prevType = family.current;
|
|
157
|
+
updatedFamiliesByType.set(prevType, family);
|
|
158
|
+
updatedFamiliesByType.set(nextType, family);
|
|
159
|
+
family.current = nextType;
|
|
158
160
|
|
|
159
161
|
// Determine whether this should be a re-render or a re-mount.
|
|
160
162
|
if (canPreserveStateBetween(prevType, nextType)) {
|
|
161
|
-
updatedFamilies.add(family)
|
|
163
|
+
updatedFamilies.add(family);
|
|
162
164
|
} else {
|
|
163
|
-
staleFamilies.add(family)
|
|
165
|
+
staleFamilies.add(family);
|
|
164
166
|
}
|
|
165
|
-
})
|
|
167
|
+
});
|
|
166
168
|
|
|
167
169
|
// TODO: rename these fields to something more meaningful.
|
|
168
170
|
const update = {
|
|
169
171
|
updatedFamilies, // Families that will re-render preserving state
|
|
170
172
|
staleFamilies, // Families that will be remounted
|
|
171
|
-
}
|
|
173
|
+
};
|
|
172
174
|
|
|
173
175
|
helpersByRendererID.forEach((helpers) => {
|
|
174
176
|
// Even if there are no roots, set the handler on first update.
|
|
175
177
|
// This ensures that if *new* roots are mounted, they'll use the resolve handler.
|
|
176
|
-
helpers.setRefreshHandler(resolveFamily)
|
|
177
|
-
})
|
|
178
|
+
helpers.setRefreshHandler(resolveFamily);
|
|
179
|
+
});
|
|
178
180
|
|
|
179
|
-
let didError = false
|
|
180
|
-
let firstError = null
|
|
181
|
+
let didError = false;
|
|
182
|
+
let firstError = null;
|
|
181
183
|
|
|
182
184
|
// We snapshot maps and sets that are mutated during commits.
|
|
183
185
|
// If we don't do this, there is a risk they will be mutated while
|
|
184
186
|
// we iterate over them. For example, trying to recover a failed root
|
|
185
187
|
// may cause another root to be added to the failed list -- an infinite loop.
|
|
186
|
-
const failedRootsSnapshot = new Set(failedRoots)
|
|
187
|
-
const mountedRootsSnapshot = new Set(mountedRoots)
|
|
188
|
-
const helpersByRootSnapshot = new Map(helpersByRoot)
|
|
188
|
+
const failedRootsSnapshot = new Set(failedRoots);
|
|
189
|
+
const mountedRootsSnapshot = new Set(mountedRoots);
|
|
190
|
+
const helpersByRootSnapshot = new Map(helpersByRoot);
|
|
189
191
|
|
|
190
192
|
failedRootsSnapshot.forEach((root) => {
|
|
191
|
-
const helpers = helpersByRootSnapshot.get(root)
|
|
193
|
+
const helpers = helpersByRootSnapshot.get(root);
|
|
192
194
|
if (helpers === undefined) {
|
|
193
|
-
throw new Error(
|
|
194
|
-
'Could not find helpers for a root. This is a bug in React Refresh.',
|
|
195
|
-
)
|
|
195
|
+
throw new Error("Could not find helpers for a root. This is a bug in React Refresh.");
|
|
196
196
|
}
|
|
197
197
|
if (!failedRoots.has(root)) {
|
|
198
198
|
// No longer failed.
|
|
199
199
|
}
|
|
200
200
|
if (rootElements === null) {
|
|
201
|
-
return
|
|
201
|
+
return;
|
|
202
202
|
}
|
|
203
203
|
if (!rootElements.has(root)) {
|
|
204
|
-
return
|
|
204
|
+
return;
|
|
205
205
|
}
|
|
206
|
-
const element = rootElements.get(root)
|
|
206
|
+
const element = rootElements.get(root);
|
|
207
207
|
try {
|
|
208
|
-
helpers.scheduleRoot(root, element)
|
|
208
|
+
helpers.scheduleRoot(root, element);
|
|
209
209
|
} catch (err) {
|
|
210
210
|
if (!didError) {
|
|
211
|
-
didError = true
|
|
212
|
-
firstError = err
|
|
211
|
+
didError = true;
|
|
212
|
+
firstError = err;
|
|
213
213
|
}
|
|
214
214
|
// Keep trying other roots.
|
|
215
215
|
}
|
|
216
|
-
})
|
|
216
|
+
});
|
|
217
217
|
mountedRootsSnapshot.forEach((root) => {
|
|
218
|
-
const helpers = helpersByRootSnapshot.get(root)
|
|
218
|
+
const helpers = helpersByRootSnapshot.get(root);
|
|
219
219
|
if (helpers === undefined) {
|
|
220
|
-
throw new Error(
|
|
221
|
-
'Could not find helpers for a root. This is a bug in React Refresh.',
|
|
222
|
-
)
|
|
220
|
+
throw new Error("Could not find helpers for a root. This is a bug in React Refresh.");
|
|
223
221
|
}
|
|
224
222
|
if (!mountedRoots.has(root)) {
|
|
225
223
|
// No longer mounted.
|
|
226
224
|
}
|
|
227
225
|
try {
|
|
228
|
-
helpers.scheduleRefresh(root, update)
|
|
226
|
+
helpers.scheduleRefresh(root, update);
|
|
229
227
|
} catch (err) {
|
|
230
228
|
if (!didError) {
|
|
231
|
-
didError = true
|
|
232
|
-
firstError = err
|
|
229
|
+
didError = true;
|
|
230
|
+
firstError = err;
|
|
233
231
|
}
|
|
234
232
|
// Keep trying other roots.
|
|
235
233
|
}
|
|
236
|
-
})
|
|
234
|
+
});
|
|
237
235
|
if (didError) {
|
|
238
|
-
throw firstError
|
|
236
|
+
throw firstError;
|
|
239
237
|
}
|
|
240
|
-
return update
|
|
238
|
+
return update;
|
|
241
239
|
} finally {
|
|
242
|
-
isPerformingRefresh = false
|
|
240
|
+
isPerformingRefresh = false;
|
|
243
241
|
}
|
|
244
242
|
}
|
|
245
243
|
|
|
246
244
|
function register(type, id) {
|
|
247
245
|
if (type === null) {
|
|
248
|
-
return
|
|
246
|
+
return;
|
|
249
247
|
}
|
|
250
|
-
if (typeof type !==
|
|
251
|
-
return
|
|
248
|
+
if (typeof type !== "function" && typeof type !== "object") {
|
|
249
|
+
return;
|
|
252
250
|
}
|
|
253
251
|
|
|
254
252
|
// This can happen in an edge case, e.g. if we register
|
|
255
253
|
// return value of a HOC but it returns a cached component.
|
|
256
254
|
// Ignore anything but the first registration for each type.
|
|
257
255
|
if (allFamiliesByType.has(type)) {
|
|
258
|
-
return
|
|
256
|
+
return;
|
|
259
257
|
}
|
|
260
258
|
// Create family or remember to update it.
|
|
261
259
|
// None of this bookkeeping affects reconciliation
|
|
262
260
|
// until the first performReactRefresh() call above.
|
|
263
|
-
let family = allFamiliesByID.get(id)
|
|
261
|
+
let family = allFamiliesByID.get(id);
|
|
264
262
|
if (family === undefined) {
|
|
265
|
-
family = { current: type }
|
|
266
|
-
allFamiliesByID.set(id, family)
|
|
263
|
+
family = { current: type };
|
|
264
|
+
allFamiliesByID.set(id, family);
|
|
267
265
|
} else {
|
|
268
|
-
pendingUpdates.push([family, type])
|
|
266
|
+
pendingUpdates.push([family, type]);
|
|
269
267
|
}
|
|
270
|
-
allFamiliesByType.set(type, family)
|
|
268
|
+
allFamiliesByType.set(type, family);
|
|
271
269
|
|
|
272
270
|
// Visit inner types because we might not have registered them.
|
|
273
|
-
if (typeof type ===
|
|
274
|
-
switch (getProperty(type,
|
|
271
|
+
if (typeof type === "object" && type !== null) {
|
|
272
|
+
switch (getProperty(type, "$$typeof")) {
|
|
275
273
|
case REACT_FORWARD_REF_TYPE:
|
|
276
|
-
register(type.render, id +
|
|
277
|
-
break
|
|
274
|
+
register(type.render, id + "$render");
|
|
275
|
+
break;
|
|
278
276
|
case REACT_MEMO_TYPE:
|
|
279
|
-
register(type.type, id +
|
|
280
|
-
break
|
|
277
|
+
register(type.type, id + "$type");
|
|
278
|
+
break;
|
|
281
279
|
}
|
|
282
280
|
}
|
|
283
281
|
}
|
|
@@ -289,17 +287,17 @@ function setSignature(type, key, forceReset, getCustomHooks) {
|
|
|
289
287
|
ownKey: key,
|
|
290
288
|
fullKey: null,
|
|
291
289
|
getCustomHooks: getCustomHooks || (() => []),
|
|
292
|
-
})
|
|
290
|
+
});
|
|
293
291
|
}
|
|
294
292
|
// Visit inner types because we might not have signed them.
|
|
295
|
-
if (typeof type ===
|
|
296
|
-
switch (getProperty(type,
|
|
293
|
+
if (typeof type === "object" && type !== null) {
|
|
294
|
+
switch (getProperty(type, "$$typeof")) {
|
|
297
295
|
case REACT_FORWARD_REF_TYPE:
|
|
298
|
-
setSignature(type.render, key, forceReset, getCustomHooks)
|
|
299
|
-
break
|
|
296
|
+
setSignature(type.render, key, forceReset, getCustomHooks);
|
|
297
|
+
break;
|
|
300
298
|
case REACT_MEMO_TYPE:
|
|
301
|
-
setSignature(type.type, key, forceReset, getCustomHooks)
|
|
302
|
-
break
|
|
299
|
+
setSignature(type.type, key, forceReset, getCustomHooks);
|
|
300
|
+
break;
|
|
303
301
|
}
|
|
304
302
|
}
|
|
305
303
|
}
|
|
@@ -307,9 +305,9 @@ function setSignature(type, key, forceReset, getCustomHooks) {
|
|
|
307
305
|
// This is lazily called during first render for a type.
|
|
308
306
|
// It captures Hook list at that time so inline requires don't break comparisons.
|
|
309
307
|
function collectCustomHooksForSignature(type) {
|
|
310
|
-
const signature = allSignaturesByType.get(type)
|
|
308
|
+
const signature = allSignaturesByType.get(type);
|
|
311
309
|
if (signature !== undefined) {
|
|
312
|
-
computeFullKey(signature)
|
|
310
|
+
computeFullKey(signature);
|
|
313
311
|
}
|
|
314
312
|
}
|
|
315
313
|
|
|
@@ -319,12 +317,12 @@ export function injectIntoGlobalHook(globalObject) {
|
|
|
319
317
|
|
|
320
318
|
// For React Web, the global hook will be set up by the extension.
|
|
321
319
|
// This will also run before us.
|
|
322
|
-
let hook = globalObject.__REACT_DEVTOOLS_GLOBAL_HOOK__
|
|
320
|
+
let hook = globalObject.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
323
321
|
if (hook === undefined) {
|
|
324
322
|
// However, if there is no DevTools extension, we'll need to set up the global hook ourselves.
|
|
325
323
|
// Note that in this case it's important that renderer code runs *after* this method call.
|
|
326
324
|
// Otherwise, the renderer will think that there is no global hook, and won't do the injection.
|
|
327
|
-
let nextID = 0
|
|
325
|
+
let nextID = 0;
|
|
328
326
|
globalObject.__REACT_DEVTOOLS_GLOBAL_HOOK__ = hook = {
|
|
329
327
|
renderers: new Map(),
|
|
330
328
|
supportsFiber: true,
|
|
@@ -332,68 +330,68 @@ export function injectIntoGlobalHook(globalObject) {
|
|
|
332
330
|
onScheduleFiberRoot: (id, root, children) => {},
|
|
333
331
|
onCommitFiberRoot: (id, root, maybePriorityLevel, didError) => {},
|
|
334
332
|
onCommitFiberUnmount() {},
|
|
335
|
-
}
|
|
333
|
+
};
|
|
336
334
|
}
|
|
337
335
|
|
|
338
336
|
if (hook.isDisabled) {
|
|
339
337
|
// This isn't a real property on the hook, but it can be set to opt out
|
|
340
338
|
// of DevTools integration and associated warnings and logs.
|
|
341
339
|
// Using console['warn'] to evade Babel and ESLint
|
|
342
|
-
console[
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
)
|
|
346
|
-
return
|
|
340
|
+
console["warn"](
|
|
341
|
+
"Something has shimmed the React DevTools global hook (__REACT_DEVTOOLS_GLOBAL_HOOK__). " +
|
|
342
|
+
"Fast Refresh is not compatible with this shim and will be disabled.",
|
|
343
|
+
);
|
|
344
|
+
return;
|
|
347
345
|
}
|
|
348
346
|
|
|
349
347
|
// Here, we just want to get a reference to scheduleRefresh.
|
|
350
|
-
const oldInject = hook.inject
|
|
348
|
+
const oldInject = hook.inject;
|
|
351
349
|
hook.inject = function (injected) {
|
|
352
|
-
const id = oldInject.apply(this, arguments)
|
|
350
|
+
const id = oldInject.apply(this, arguments);
|
|
353
351
|
if (
|
|
354
|
-
typeof injected.scheduleRefresh ===
|
|
355
|
-
typeof injected.setRefreshHandler ===
|
|
352
|
+
typeof injected.scheduleRefresh === "function" &&
|
|
353
|
+
typeof injected.setRefreshHandler === "function"
|
|
356
354
|
) {
|
|
357
355
|
// This version supports React Refresh.
|
|
358
|
-
helpersByRendererID.set(id, injected)
|
|
356
|
+
helpersByRendererID.set(id, injected);
|
|
359
357
|
}
|
|
360
|
-
return id
|
|
361
|
-
}
|
|
358
|
+
return id;
|
|
359
|
+
};
|
|
362
360
|
|
|
363
361
|
// Do the same for any already injected roots.
|
|
364
362
|
// This is useful if ReactDOM has already been initialized.
|
|
365
363
|
// https://github.com/facebook/react/issues/17626
|
|
366
364
|
hook.renderers.forEach((injected, id) => {
|
|
367
365
|
if (
|
|
368
|
-
typeof injected.scheduleRefresh ===
|
|
369
|
-
typeof injected.setRefreshHandler ===
|
|
366
|
+
typeof injected.scheduleRefresh === "function" &&
|
|
367
|
+
typeof injected.setRefreshHandler === "function"
|
|
370
368
|
) {
|
|
371
369
|
// This version supports React Refresh.
|
|
372
|
-
helpersByRendererID.set(id, injected)
|
|
370
|
+
helpersByRendererID.set(id, injected);
|
|
373
371
|
}
|
|
374
|
-
})
|
|
372
|
+
});
|
|
375
373
|
|
|
376
374
|
// We also want to track currently mounted roots.
|
|
377
|
-
const oldOnCommitFiberRoot = hook.onCommitFiberRoot
|
|
378
|
-
const oldOnScheduleFiberRoot = hook.onScheduleFiberRoot || (() => {})
|
|
375
|
+
const oldOnCommitFiberRoot = hook.onCommitFiberRoot;
|
|
376
|
+
const oldOnScheduleFiberRoot = hook.onScheduleFiberRoot || (() => {});
|
|
379
377
|
hook.onScheduleFiberRoot = function (id, root, children) {
|
|
380
378
|
if (!isPerformingRefresh) {
|
|
381
379
|
// If it was intentionally scheduled, don't attempt to restore.
|
|
382
380
|
// This includes intentionally scheduled unmounts.
|
|
383
|
-
failedRoots.delete(root)
|
|
381
|
+
failedRoots.delete(root);
|
|
384
382
|
if (rootElements !== null) {
|
|
385
|
-
rootElements.set(root, children)
|
|
383
|
+
rootElements.set(root, children);
|
|
386
384
|
}
|
|
387
385
|
}
|
|
388
|
-
return oldOnScheduleFiberRoot.apply(this, arguments)
|
|
389
|
-
}
|
|
386
|
+
return oldOnScheduleFiberRoot.apply(this, arguments);
|
|
387
|
+
};
|
|
390
388
|
hook.onCommitFiberRoot = function (id, root, maybePriorityLevel, didError) {
|
|
391
|
-
const helpers = helpersByRendererID.get(id)
|
|
389
|
+
const helpers = helpersByRendererID.get(id);
|
|
392
390
|
if (helpers !== undefined) {
|
|
393
|
-
helpersByRoot.set(root, helpers)
|
|
391
|
+
helpersByRoot.set(root, helpers);
|
|
394
392
|
|
|
395
|
-
const current = root.current
|
|
396
|
-
const alternate = current.alternate
|
|
393
|
+
const current = root.current;
|
|
394
|
+
const alternate = current.alternate;
|
|
397
395
|
|
|
398
396
|
// We need to determine whether this root has just (un)mounted.
|
|
399
397
|
// This logic is copy-pasted from similar logic in the DevTools backend.
|
|
@@ -403,42 +401,41 @@ export function injectIntoGlobalHook(globalObject) {
|
|
|
403
401
|
const wasMounted =
|
|
404
402
|
alternate.memoizedState != null &&
|
|
405
403
|
alternate.memoizedState.element != null &&
|
|
406
|
-
mountedRoots.has(root)
|
|
404
|
+
mountedRoots.has(root);
|
|
407
405
|
|
|
408
|
-
const isMounted =
|
|
409
|
-
current.memoizedState != null && current.memoizedState.element != null
|
|
406
|
+
const isMounted = current.memoizedState != null && current.memoizedState.element != null;
|
|
410
407
|
|
|
411
408
|
if (!wasMounted && isMounted) {
|
|
412
409
|
// Mount a new root.
|
|
413
|
-
mountedRoots.add(root)
|
|
414
|
-
failedRoots.delete(root)
|
|
410
|
+
mountedRoots.add(root);
|
|
411
|
+
failedRoots.delete(root);
|
|
415
412
|
} else if (wasMounted && isMounted) {
|
|
416
413
|
// Update an existing root.
|
|
417
414
|
// This doesn't affect our mounted root Set.
|
|
418
415
|
} else if (wasMounted && !isMounted) {
|
|
419
416
|
// Unmount an existing root.
|
|
420
|
-
mountedRoots.delete(root)
|
|
417
|
+
mountedRoots.delete(root);
|
|
421
418
|
if (didError) {
|
|
422
419
|
// We'll remount it on future edits.
|
|
423
|
-
failedRoots.add(root)
|
|
420
|
+
failedRoots.add(root);
|
|
424
421
|
} else {
|
|
425
|
-
helpersByRoot.delete(root)
|
|
422
|
+
helpersByRoot.delete(root);
|
|
426
423
|
}
|
|
427
424
|
} else if (!wasMounted && !isMounted) {
|
|
428
425
|
if (didError) {
|
|
429
426
|
// We'll remount it on future edits.
|
|
430
|
-
failedRoots.add(root)
|
|
427
|
+
failedRoots.add(root);
|
|
431
428
|
}
|
|
432
429
|
}
|
|
433
430
|
} else {
|
|
434
431
|
// Mount a new root.
|
|
435
|
-
mountedRoots.add(root)
|
|
432
|
+
mountedRoots.add(root);
|
|
436
433
|
}
|
|
437
434
|
}
|
|
438
435
|
|
|
439
436
|
// Always call the decorated DevTools hook.
|
|
440
|
-
return oldOnCommitFiberRoot.apply(this, arguments)
|
|
441
|
-
}
|
|
437
|
+
return oldOnCommitFiberRoot.apply(this, arguments);
|
|
438
|
+
};
|
|
442
439
|
}
|
|
443
440
|
|
|
444
441
|
// This is a wrapper over more primitive functions for setting signature.
|
|
@@ -464,100 +461,97 @@ export function injectIntoGlobalHook(globalObject) {
|
|
|
464
461
|
// () => [useCustomHook], /* Lazy to avoid triggering inline requires */
|
|
465
462
|
// );
|
|
466
463
|
export function createSignatureFunctionForTransform() {
|
|
467
|
-
let savedType
|
|
468
|
-
let hasCustomHooks
|
|
469
|
-
let didCollectHooks = false
|
|
464
|
+
let savedType;
|
|
465
|
+
let hasCustomHooks;
|
|
466
|
+
let didCollectHooks = false;
|
|
470
467
|
return function (type, key, forceReset, getCustomHooks) {
|
|
471
|
-
if (typeof key ===
|
|
468
|
+
if (typeof key === "string") {
|
|
472
469
|
// We're in the initial phase that associates signatures
|
|
473
470
|
// with the functions. Note this may be called multiple times
|
|
474
471
|
// in HOC chains like _s(hoc1(_s(hoc2(_s(actualFunction))))).
|
|
475
472
|
if (!savedType) {
|
|
476
473
|
// We're in the innermost call, so this is the actual type.
|
|
477
474
|
// $FlowFixMe[escaped-generic] discovered when updating Flow
|
|
478
|
-
savedType = type
|
|
479
|
-
hasCustomHooks = typeof getCustomHooks ===
|
|
475
|
+
savedType = type;
|
|
476
|
+
hasCustomHooks = typeof getCustomHooks === "function";
|
|
480
477
|
}
|
|
481
478
|
// Set the signature for all types (even wrappers!) in case
|
|
482
479
|
// they have no signatures of their own. This is to prevent
|
|
483
480
|
// problems like https://github.com/facebook/react/issues/20417.
|
|
484
|
-
if (
|
|
485
|
-
type
|
|
486
|
-
(typeof type === 'function' || typeof type === 'object')
|
|
487
|
-
) {
|
|
488
|
-
setSignature(type, key, forceReset, getCustomHooks)
|
|
481
|
+
if (type != null && (typeof type === "function" || typeof type === "object")) {
|
|
482
|
+
setSignature(type, key, forceReset, getCustomHooks);
|
|
489
483
|
}
|
|
490
|
-
return type
|
|
484
|
+
return type;
|
|
491
485
|
} else {
|
|
492
486
|
// We're in the _s() call without arguments, which means
|
|
493
487
|
// this is the time to collect custom Hook signatures.
|
|
494
488
|
// Only do this once. This path is hot and runs *inside* every render!
|
|
495
489
|
if (!didCollectHooks && hasCustomHooks) {
|
|
496
|
-
didCollectHooks = true
|
|
497
|
-
collectCustomHooksForSignature(savedType)
|
|
490
|
+
didCollectHooks = true;
|
|
491
|
+
collectCustomHooksForSignature(savedType);
|
|
498
492
|
}
|
|
499
493
|
}
|
|
500
|
-
}
|
|
494
|
+
};
|
|
501
495
|
}
|
|
502
496
|
|
|
503
497
|
function isLikelyComponentType(type) {
|
|
504
498
|
switch (typeof type) {
|
|
505
|
-
case
|
|
499
|
+
case "function": {
|
|
506
500
|
// First, deal with classes.
|
|
507
501
|
if (type.prototype != null) {
|
|
508
502
|
if (type.prototype.isReactComponent) {
|
|
509
503
|
// React class.
|
|
510
|
-
return true
|
|
504
|
+
return true;
|
|
511
505
|
}
|
|
512
|
-
const ownNames = Object.getOwnPropertyNames(type.prototype)
|
|
513
|
-
if (ownNames.length > 1 || ownNames[0] !==
|
|
506
|
+
const ownNames = Object.getOwnPropertyNames(type.prototype);
|
|
507
|
+
if (ownNames.length > 1 || ownNames[0] !== "constructor") {
|
|
514
508
|
// This looks like a class.
|
|
515
|
-
return false
|
|
509
|
+
return false;
|
|
516
510
|
}
|
|
517
511
|
|
|
518
512
|
if (type.prototype.__proto__ !== Object.prototype) {
|
|
519
513
|
// It has a superclass.
|
|
520
|
-
return false
|
|
514
|
+
return false;
|
|
521
515
|
}
|
|
522
516
|
// Pass through.
|
|
523
517
|
// This looks like a regular function with empty prototype.
|
|
524
518
|
}
|
|
525
519
|
// For plain functions and arrows, use name as a heuristic.
|
|
526
|
-
const name = type.name || type.displayName
|
|
527
|
-
return typeof name ===
|
|
520
|
+
const name = type.name || type.displayName;
|
|
521
|
+
return typeof name === "string" && /^[A-Z]/.test(name);
|
|
528
522
|
}
|
|
529
|
-
case
|
|
523
|
+
case "object": {
|
|
530
524
|
if (type != null) {
|
|
531
|
-
switch (getProperty(type,
|
|
525
|
+
switch (getProperty(type, "$$typeof")) {
|
|
532
526
|
case REACT_FORWARD_REF_TYPE:
|
|
533
527
|
case REACT_MEMO_TYPE:
|
|
534
528
|
// Definitely React components.
|
|
535
|
-
return true
|
|
529
|
+
return true;
|
|
536
530
|
default:
|
|
537
|
-
return false
|
|
531
|
+
return false;
|
|
538
532
|
}
|
|
539
533
|
}
|
|
540
|
-
return false
|
|
534
|
+
return false;
|
|
541
535
|
}
|
|
542
536
|
default: {
|
|
543
|
-
return false
|
|
537
|
+
return false;
|
|
544
538
|
}
|
|
545
539
|
}
|
|
546
540
|
}
|
|
547
541
|
|
|
548
542
|
function isCompoundComponent(type) {
|
|
549
|
-
if (!isPlainObject(type)) return false
|
|
543
|
+
if (!isPlainObject(type)) return false;
|
|
550
544
|
for (const key in type) {
|
|
551
|
-
if (!isLikelyComponentType(type[key])) return false
|
|
545
|
+
if (!isLikelyComponentType(type[key])) return false;
|
|
552
546
|
}
|
|
553
|
-
return true
|
|
547
|
+
return true;
|
|
554
548
|
}
|
|
555
549
|
|
|
556
550
|
function isPlainObject(obj) {
|
|
557
551
|
return (
|
|
558
|
-
Object.prototype.toString.call(obj) ===
|
|
552
|
+
Object.prototype.toString.call(obj) === "[object Object]" &&
|
|
559
553
|
(obj.constructor === Object || obj.constructor === undefined)
|
|
560
|
-
)
|
|
554
|
+
);
|
|
561
555
|
}
|
|
562
556
|
|
|
563
557
|
/**
|
|
@@ -565,106 +559,87 @@ function isPlainObject(obj) {
|
|
|
565
559
|
*/
|
|
566
560
|
|
|
567
561
|
export function getRefreshReg(filename) {
|
|
568
|
-
return (type, id) => register(type, filename +
|
|
562
|
+
return (type, id) => register(type, filename + " " + id);
|
|
569
563
|
}
|
|
570
564
|
|
|
571
565
|
// Taken from https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/lib/runtime/RefreshUtils.js#L141
|
|
572
566
|
// This allows to resister components not detected by SWC like styled component
|
|
573
567
|
export function registerExportsForReactRefresh(filename, moduleExports) {
|
|
574
568
|
for (const key in moduleExports) {
|
|
575
|
-
if (key ===
|
|
576
|
-
const exportValue = moduleExports[key]
|
|
569
|
+
if (key === "__esModule") continue;
|
|
570
|
+
const exportValue = moduleExports[key];
|
|
577
571
|
if (isLikelyComponentType(exportValue)) {
|
|
578
572
|
// 'export' is required to avoid key collision when renamed exports that
|
|
579
573
|
// shadow a local component name: https://github.com/vitejs/vite-plugin-react/issues/116
|
|
580
574
|
// The register function has an identity check to not register twice the same component,
|
|
581
575
|
// so this is safe to not used the same key here.
|
|
582
|
-
register(exportValue, filename +
|
|
576
|
+
register(exportValue, filename + " export " + key);
|
|
583
577
|
} else if (isCompoundComponent(exportValue)) {
|
|
584
578
|
for (const subKey in exportValue) {
|
|
585
|
-
register(
|
|
586
|
-
exportValue[subKey],
|
|
587
|
-
filename + ' export ' + key + '-' + subKey,
|
|
588
|
-
)
|
|
579
|
+
register(exportValue[subKey], filename + " export " + key + "-" + subKey);
|
|
589
580
|
}
|
|
590
581
|
}
|
|
591
582
|
}
|
|
592
583
|
}
|
|
593
584
|
|
|
594
585
|
function debounce(fn, delay) {
|
|
595
|
-
let handle
|
|
586
|
+
let handle;
|
|
596
587
|
return () => {
|
|
597
|
-
clearTimeout(handle)
|
|
598
|
-
handle = setTimeout(fn, delay)
|
|
599
|
-
}
|
|
588
|
+
clearTimeout(handle);
|
|
589
|
+
handle = setTimeout(fn, delay);
|
|
590
|
+
};
|
|
600
591
|
}
|
|
601
592
|
|
|
602
|
-
const hooks = []
|
|
593
|
+
const hooks = [];
|
|
603
594
|
window.__registerBeforePerformReactRefresh = (cb) => {
|
|
604
|
-
hooks.push(cb)
|
|
605
|
-
}
|
|
595
|
+
hooks.push(cb);
|
|
596
|
+
};
|
|
606
597
|
const enqueueUpdate = debounce(async () => {
|
|
607
|
-
if (hooks.length) await Promise.all(hooks.map((cb) => cb()))
|
|
608
|
-
performReactRefresh()
|
|
609
|
-
}, 16)
|
|
610
|
-
|
|
611
|
-
export function validateRefreshBoundaryAndEnqueueUpdate(
|
|
612
|
-
id
|
|
613
|
-
prevExports,
|
|
614
|
-
|
|
615
|
-
) {
|
|
616
|
-
const ignoredExports = window.__getReactRefreshIgnoredExports?.({ id }) ?? []
|
|
617
|
-
if (
|
|
618
|
-
predicateOnExport(
|
|
619
|
-
ignoredExports,
|
|
620
|
-
prevExports,
|
|
621
|
-
(key) => key in nextExports,
|
|
622
|
-
) !== true
|
|
623
|
-
) {
|
|
624
|
-
return 'Could not Fast Refresh (export removed)'
|
|
598
|
+
if (hooks.length) await Promise.all(hooks.map((cb) => cb()));
|
|
599
|
+
performReactRefresh();
|
|
600
|
+
}, 16);
|
|
601
|
+
|
|
602
|
+
export function validateRefreshBoundaryAndEnqueueUpdate(id, prevExports, nextExports) {
|
|
603
|
+
const ignoredExports = window.__getReactRefreshIgnoredExports?.({ id }) ?? [];
|
|
604
|
+
if (predicateOnExport(ignoredExports, prevExports, (key) => key in nextExports) !== true) {
|
|
605
|
+
return "Could not Fast Refresh (export removed)";
|
|
625
606
|
}
|
|
626
|
-
if (
|
|
627
|
-
|
|
628
|
-
ignoredExports,
|
|
629
|
-
nextExports,
|
|
630
|
-
(key) => key in prevExports,
|
|
631
|
-
) !== true
|
|
632
|
-
) {
|
|
633
|
-
return 'Could not Fast Refresh (new export)'
|
|
607
|
+
if (predicateOnExport(ignoredExports, nextExports, (key) => key in prevExports) !== true) {
|
|
608
|
+
return "Could not Fast Refresh (new export)";
|
|
634
609
|
}
|
|
635
610
|
|
|
636
|
-
let hasExports = false
|
|
611
|
+
let hasExports = false;
|
|
637
612
|
const allExportsAreComponentsOrUnchanged = predicateOnExport(
|
|
638
613
|
ignoredExports,
|
|
639
614
|
nextExports,
|
|
640
615
|
(key, value) => {
|
|
641
|
-
hasExports = true
|
|
642
|
-
if (isLikelyComponentType(value)) return true
|
|
643
|
-
if (isCompoundComponent(value)) return true
|
|
644
|
-
return prevExports[key] === nextExports[key]
|
|
616
|
+
hasExports = true;
|
|
617
|
+
if (isLikelyComponentType(value)) return true;
|
|
618
|
+
if (isCompoundComponent(value)) return true;
|
|
619
|
+
return prevExports[key] === nextExports[key];
|
|
645
620
|
},
|
|
646
|
-
)
|
|
621
|
+
);
|
|
647
622
|
if (hasExports && allExportsAreComponentsOrUnchanged === true) {
|
|
648
|
-
enqueueUpdate()
|
|
623
|
+
enqueueUpdate();
|
|
649
624
|
} else {
|
|
650
|
-
return `Could not Fast Refresh ("${allExportsAreComponentsOrUnchanged}" export is incompatible). Learn more at __README_URL__#consistent-components-exports
|
|
625
|
+
return `Could not Fast Refresh ("${allExportsAreComponentsOrUnchanged}" export is incompatible). Learn more at __README_URL__#consistent-components-exports`;
|
|
651
626
|
}
|
|
652
627
|
}
|
|
653
628
|
|
|
654
629
|
function predicateOnExport(ignoredExports, moduleExports, predicate) {
|
|
655
630
|
for (const key in moduleExports) {
|
|
656
|
-
if (key ===
|
|
657
|
-
if (ignoredExports.includes(key)) continue
|
|
658
|
-
const desc = Object.getOwnPropertyDescriptor(moduleExports, key)
|
|
659
|
-
if (desc && desc.get) return key
|
|
660
|
-
if (!predicate(key, moduleExports[key])) return key
|
|
631
|
+
if (key === "__esModule") continue;
|
|
632
|
+
if (ignoredExports.includes(key)) continue;
|
|
633
|
+
const desc = Object.getOwnPropertyDescriptor(moduleExports, key);
|
|
634
|
+
if (desc && desc.get) return key;
|
|
635
|
+
if (!predicate(key, moduleExports[key])) return key;
|
|
661
636
|
}
|
|
662
|
-
return true
|
|
637
|
+
return true;
|
|
663
638
|
}
|
|
664
639
|
|
|
665
640
|
// Hides vite-ignored dynamic import so that Vite can skip analysis if no other
|
|
666
641
|
// dynamic import is present (https://github.com/vitejs/vite/pull/12732)
|
|
667
|
-
export const __hmr_import = (module) => import(/* @vite-ignore */ module)
|
|
642
|
+
export const __hmr_import = (module) => import(/* @vite-ignore */ module);
|
|
668
643
|
|
|
669
644
|
// For backwards compatibility with @vitejs/plugin-react.
|
|
670
|
-
export default { injectIntoGlobalHook }
|
|
645
|
+
export default { injectIntoGlobalHook };
|