@reckona/mreact-compat 0.0.91 → 0.0.92
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/README.md +1 -0
- package/dist/class-component.d.ts +20 -6
- package/dist/class-component.d.ts.map +1 -1
- package/dist/class-component.js +94 -51
- package/dist/class-component.js.map +1 -1
- package/dist/context.d.ts +19 -3
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +55 -6
- package/dist/context.js.map +1 -1
- package/dist/dom-children.d.ts +2 -0
- package/dist/dom-children.d.ts.map +1 -1
- package/dist/dom-children.js +103 -1
- package/dist/dom-children.js.map +1 -1
- package/dist/dom-host-rules.d.ts +10 -0
- package/dist/dom-host-rules.d.ts.map +1 -0
- package/dist/dom-host-rules.js +86 -0
- package/dist/dom-host-rules.js.map +1 -0
- package/dist/dom-props.d.ts +3 -2
- package/dist/dom-props.d.ts.map +1 -1
- package/dist/dom-props.js +229 -33
- package/dist/dom-props.js.map +1 -1
- package/dist/element.d.ts +9 -4
- package/dist/element.d.ts.map +1 -1
- package/dist/element.js +101 -26
- package/dist/element.js.map +1 -1
- package/dist/event-listeners.d.ts +4 -4
- package/dist/event-listeners.d.ts.map +1 -1
- package/dist/event-listeners.js +1 -1
- package/dist/event-listeners.js.map +1 -1
- package/dist/event-types.d.ts +10 -0
- package/dist/event-types.d.ts.map +1 -1
- package/dist/event-types.js.map +1 -1
- package/dist/events.js +22 -1
- package/dist/events.js.map +1 -1
- package/dist/fiber-commit.d.ts +2 -1
- package/dist/fiber-commit.d.ts.map +1 -1
- package/dist/fiber-commit.js +13 -1
- package/dist/fiber-commit.js.map +1 -1
- package/dist/fiber-reconciler.d.ts.map +1 -1
- package/dist/fiber-reconciler.js +28 -7
- package/dist/fiber-reconciler.js.map +1 -1
- package/dist/fiber-work-loop.d.ts.map +1 -1
- package/dist/fiber-work-loop.js +4 -3
- package/dist/fiber-work-loop.js.map +1 -1
- package/dist/fiber.d.ts +5 -0
- package/dist/fiber.d.ts.map +1 -1
- package/dist/fiber.js +9 -0
- package/dist/fiber.js.map +1 -1
- package/dist/hooks-entry.d.ts +3 -0
- package/dist/hooks-entry.d.ts.map +1 -0
- package/dist/hooks-entry.js +2 -0
- package/dist/hooks-entry.js.map +1 -0
- package/dist/hooks.d.ts +39 -5
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +373 -326
- package/dist/hooks.js.map +1 -1
- package/dist/host-reconciler.d.ts +3 -0
- package/dist/host-reconciler.d.ts.map +1 -1
- package/dist/host-reconciler.js +1152 -64
- package/dist/host-reconciler.js.map +1 -1
- package/dist/hydration.d.ts +1 -1
- package/dist/hydration.d.ts.map +1 -1
- package/dist/hydration.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/react-default.d.ts +4 -4
- package/dist/react-default.d.ts.map +1 -1
- package/dist/react-default.js +2 -1
- package/dist/react-default.js.map +1 -1
- package/dist/reconciler.d.ts.map +1 -1
- package/dist/reconciler.js +38 -22
- package/dist/reconciler.js.map +1 -1
- package/dist/root.d.ts.map +1 -1
- package/dist/root.js +48 -13
- package/dist/root.js.map +1 -1
- package/dist/server-render.d.ts +6 -0
- package/dist/server-render.d.ts.map +1 -0
- package/dist/server-render.js +307 -0
- package/dist/server-render.js.map +1 -0
- package/package.json +6 -2
- package/src/class-component.ts +216 -51
- package/src/context.ts +108 -9
- package/src/dom-children.ts +155 -1
- package/src/dom-host-rules.ts +115 -0
- package/src/dom-props.ts +297 -46
- package/src/element.ts +141 -31
- package/src/event-listeners.ts +6 -6
- package/src/event-types.ts +10 -0
- package/src/events.ts +32 -10
- package/src/fiber-commit.ts +16 -1
- package/src/fiber-reconciler.ts +39 -6
- package/src/fiber-work-loop.ts +4 -3
- package/src/fiber.ts +14 -0
- package/src/hooks-entry.ts +24 -0
- package/src/hooks.ts +482 -479
- package/src/host-reconciler.ts +1628 -94
- package/src/hydration.ts +1 -1
- package/src/index.ts +1 -1
- package/src/react-default.ts +1 -1
- package/src/reconciler.ts +61 -22
- package/src/root.ts +55 -12
- package/src/server-render.ts +478 -0
package/dist/hooks.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { scheduleCallback } from "./fiber-scheduler.js";
|
|
2
|
-
import {
|
|
3
|
-
import { isReactCompatContext,
|
|
2
|
+
import { removeChildIfPresent } from "./dom-children.js";
|
|
3
|
+
import { isReactCompatContext, readContextValue, useContext, withContextReadObserver, } from "./context.js";
|
|
4
4
|
import { isThenable } from "./thenable.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
const HOOK_RENDER_STATE_KEY = Symbol.for("modular.react.hook_render_state");
|
|
6
|
+
const hookRenderState = (globalThis[HOOK_RENDER_STATE_KEY] ??= {
|
|
7
|
+
currentRuntime: undefined,
|
|
8
|
+
currentInstance: undefined,
|
|
9
|
+
currentCacheScope: undefined,
|
|
10
|
+
hostCommitDepth: 0,
|
|
11
|
+
queuedHostCommitRerenders: new Set(),
|
|
12
|
+
queuedEffectFlushRerenders: new Set(),
|
|
13
|
+
});
|
|
10
14
|
const CACHE_SCOPE_SYMBOL = Symbol.for("modular.react.cache_scope");
|
|
11
15
|
const emptyCacheOwnerStack = [];
|
|
12
16
|
let syncVersion = 0;
|
|
@@ -17,12 +21,64 @@ let transitionRerenderScheduled = false;
|
|
|
17
21
|
let eventBatchDepth = 0;
|
|
18
22
|
let currentEventPriority = "default";
|
|
19
23
|
let eventRerenderScheduled = false;
|
|
24
|
+
let effectFlushRerenderDepth = 0;
|
|
25
|
+
let strictMemoOwnerId = 0;
|
|
26
|
+
const strictMemoObjectOwnerIds = new WeakMap();
|
|
27
|
+
const strictMemoPrimitiveOwnerIds = new Map();
|
|
20
28
|
const queuedTransitionRerenders = new Map();
|
|
21
29
|
const queuedEventRerenders = new Set();
|
|
22
30
|
export const version = "19.2.6";
|
|
23
31
|
export function act(callback) {
|
|
24
|
-
const
|
|
25
|
-
|
|
32
|
+
const previousPriority = currentEventPriority;
|
|
33
|
+
currentEventPriority = "discrete";
|
|
34
|
+
eventBatchDepth += 1;
|
|
35
|
+
let result;
|
|
36
|
+
try {
|
|
37
|
+
result = callback();
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
eventBatchDepth -= 1;
|
|
41
|
+
currentEventPriority = previousPriority;
|
|
42
|
+
if (eventBatchDepth === 0) {
|
|
43
|
+
flushEventRerendersForPriority("discrete");
|
|
44
|
+
}
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
const finishActScope = () => {
|
|
48
|
+
eventBatchDepth -= 1;
|
|
49
|
+
currentEventPriority = previousPriority;
|
|
50
|
+
if (eventBatchDepth === 0) {
|
|
51
|
+
flushEventRerendersForPriority("discrete");
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
if (isThenable(result)) {
|
|
55
|
+
return Promise.resolve(result).then(async () => {
|
|
56
|
+
finishActScope();
|
|
57
|
+
await flushActWorkAsync();
|
|
58
|
+
}, (error) => {
|
|
59
|
+
finishActScope();
|
|
60
|
+
throw error;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
finishActScope();
|
|
64
|
+
flushActWork();
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
async function flushActWorkAsync() {
|
|
68
|
+
for (let attempt = 0; attempt < 10; attempt += 1) {
|
|
69
|
+
await Promise.resolve();
|
|
70
|
+
flushActWork();
|
|
71
|
+
}
|
|
72
|
+
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
73
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
74
|
+
flushActWork();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function flushActWork() {
|
|
78
|
+
flushQueuedEventRerenders("sync");
|
|
79
|
+
flushQueuedTransitionRerenders();
|
|
80
|
+
flushHostCommitRerenders();
|
|
81
|
+
flushEffectFlushRerenders();
|
|
26
82
|
}
|
|
27
83
|
export function createRootRuntime(rerender, options = {}) {
|
|
28
84
|
return {
|
|
@@ -37,11 +93,19 @@ export function createRootRuntime(rerender, options = {}) {
|
|
|
37
93
|
pendingEffects: [],
|
|
38
94
|
externalStoreChecks: [],
|
|
39
95
|
portalContainers: new Set(),
|
|
96
|
+
portalNodes: new Map(),
|
|
40
97
|
idCounter: 0,
|
|
41
98
|
identifierPrefix: options.identifierPrefix ?? "",
|
|
42
99
|
idMode: options.idMode ?? "client",
|
|
43
100
|
strictModeDepth: 0,
|
|
101
|
+
strictReplayDepth: 0,
|
|
102
|
+
strictMemoCapture: undefined,
|
|
103
|
+
strictMemoCaptureByHook: undefined,
|
|
104
|
+
strictMemoReplay: undefined,
|
|
105
|
+
strictMemoReplayByHook: undefined,
|
|
44
106
|
profilerFlushDepth: 0,
|
|
107
|
+
effectFlushPhase: undefined,
|
|
108
|
+
externalStoreUpdate: false,
|
|
45
109
|
rerender,
|
|
46
110
|
beginRender() {
|
|
47
111
|
this.activeInstanceKeys = new Set();
|
|
@@ -65,24 +129,34 @@ export function createRootRuntime(rerender, options = {}) {
|
|
|
65
129
|
}
|
|
66
130
|
this.activeInstanceKeys = undefined;
|
|
67
131
|
this.activeProfilerPaths = undefined;
|
|
68
|
-
currentRuntime = undefined;
|
|
69
|
-
currentInstance = undefined;
|
|
132
|
+
hookRenderState.currentRuntime = undefined;
|
|
133
|
+
hookRenderState.currentInstance = undefined;
|
|
70
134
|
if (committed) {
|
|
71
135
|
flushProfilerCommits(this, profilerCommits);
|
|
136
|
+
flushHostCommitRerenders();
|
|
137
|
+
this.externalStoreUpdate = false;
|
|
72
138
|
}
|
|
73
139
|
},
|
|
74
140
|
flushEffects() {
|
|
75
141
|
this.profilerFlushDepth += 1;
|
|
76
142
|
try {
|
|
143
|
+
this.effectFlushPhase = "insertion";
|
|
77
144
|
flushPendingEffects(this.pendingInsertionEffects);
|
|
145
|
+
this.effectFlushPhase = "layout";
|
|
78
146
|
const strictLayoutEffects = flushPendingEffects(this.pendingLayoutEffects);
|
|
147
|
+
this.effectFlushPhase = "normal";
|
|
79
148
|
const strictEffects = flushPendingEffects(this.pendingEffects);
|
|
149
|
+
this.effectFlushPhase = undefined;
|
|
80
150
|
const strictReplayEffects = [...strictLayoutEffects, ...strictEffects];
|
|
81
151
|
cleanupStrictEffects(strictReplayEffects);
|
|
82
152
|
replayStrictEffects(strictReplayEffects);
|
|
83
153
|
}
|
|
84
154
|
finally {
|
|
155
|
+
this.effectFlushPhase = undefined;
|
|
85
156
|
this.profilerFlushDepth -= 1;
|
|
157
|
+
if (this.profilerFlushDepth === 0) {
|
|
158
|
+
flushEffectFlushRerenders();
|
|
159
|
+
}
|
|
86
160
|
}
|
|
87
161
|
},
|
|
88
162
|
dispose() {
|
|
@@ -96,10 +170,7 @@ export function createRootRuntime(rerender, options = {}) {
|
|
|
96
170
|
this.activeProfilerPaths = undefined;
|
|
97
171
|
this.mountedProfilerPaths.clear();
|
|
98
172
|
this.profilerBaseDurations.clear();
|
|
99
|
-
|
|
100
|
-
container.replaceChildren();
|
|
101
|
-
}
|
|
102
|
-
this.portalContainers.clear();
|
|
173
|
+
clearRuntimePortalNodes(this);
|
|
103
174
|
},
|
|
104
175
|
};
|
|
105
176
|
}
|
|
@@ -116,31 +187,31 @@ export function refreshCacheScope(scope) {
|
|
|
116
187
|
scope.controller = new AbortController();
|
|
117
188
|
}
|
|
118
189
|
export function runWithCacheScope(scope, callback) {
|
|
119
|
-
const previousScope = currentCacheScope;
|
|
190
|
+
const previousScope = hookRenderState.currentCacheScope;
|
|
120
191
|
const previousGlobalScope = getGlobalCacheScope();
|
|
121
|
-
currentCacheScope = scope;
|
|
192
|
+
hookRenderState.currentCacheScope = scope;
|
|
122
193
|
setGlobalCacheScope(scope);
|
|
123
194
|
try {
|
|
124
195
|
const result = callback();
|
|
125
196
|
if (isThenable(result)) {
|
|
126
197
|
return Promise.resolve(result).finally(() => {
|
|
127
|
-
currentCacheScope = previousScope;
|
|
198
|
+
hookRenderState.currentCacheScope = previousScope;
|
|
128
199
|
setGlobalCacheScope(previousGlobalScope);
|
|
129
200
|
});
|
|
130
201
|
}
|
|
131
|
-
currentCacheScope = previousScope;
|
|
202
|
+
hookRenderState.currentCacheScope = previousScope;
|
|
132
203
|
setGlobalCacheScope(previousGlobalScope);
|
|
133
204
|
return result;
|
|
134
205
|
}
|
|
135
206
|
catch (error) {
|
|
136
|
-
currentCacheScope = previousScope;
|
|
207
|
+
hookRenderState.currentCacheScope = previousScope;
|
|
137
208
|
setGlobalCacheScope(previousGlobalScope);
|
|
138
209
|
throw error;
|
|
139
210
|
}
|
|
140
211
|
}
|
|
141
212
|
export function renderWithProfiler(runtime, path, props, render) {
|
|
142
213
|
const startTime = getCurrentTime();
|
|
143
|
-
const phase = runtime.profilerFlushDepth > 0
|
|
214
|
+
const phase = runtime.profilerFlushDepth > 0 || effectFlushRerenderDepth > 0
|
|
144
215
|
? "nested-update"
|
|
145
216
|
: runtime.mountedProfilerPaths.has(path)
|
|
146
217
|
? "update"
|
|
@@ -167,10 +238,17 @@ export function renderWithProfiler(runtime, path, props, render) {
|
|
|
167
238
|
}
|
|
168
239
|
}
|
|
169
240
|
}
|
|
170
|
-
export function renderWithRootRuntime(runtime, path, render) {
|
|
171
|
-
const previousRuntime = currentRuntime;
|
|
172
|
-
const previousInstance = currentInstance;
|
|
173
|
-
|
|
241
|
+
export function renderWithRootRuntime(runtime, path, render, owner) {
|
|
242
|
+
const previousRuntime = hookRenderState.currentRuntime;
|
|
243
|
+
const previousInstance = hookRenderState.currentInstance;
|
|
244
|
+
let instance = runtime.instances.get(path);
|
|
245
|
+
if (instance !== undefined && owner !== undefined && instance.owner !== owner) {
|
|
246
|
+
cleanupInstance(instance);
|
|
247
|
+
instance = undefined;
|
|
248
|
+
}
|
|
249
|
+
instance ??= {
|
|
250
|
+
owner,
|
|
251
|
+
path,
|
|
174
252
|
hooks: [],
|
|
175
253
|
hookIndex: 0,
|
|
176
254
|
dirty: false,
|
|
@@ -178,23 +256,46 @@ export function renderWithRootRuntime(runtime, path, render) {
|
|
|
178
256
|
devToolsHookTypes: [],
|
|
179
257
|
devToolsHookSuppressionDepth: 0,
|
|
180
258
|
};
|
|
259
|
+
instance.owner = owner;
|
|
260
|
+
instance.path = path;
|
|
181
261
|
runtime.instances.set(path, instance);
|
|
182
262
|
runtime.activeInstanceKeys?.add(path);
|
|
183
263
|
instance.hookIndex = 0;
|
|
184
264
|
instance.dirty = false;
|
|
265
|
+
instance.disposed = false;
|
|
266
|
+
delete instance.contextDependencies;
|
|
185
267
|
instance.devToolsHooks = [];
|
|
186
268
|
instance.devToolsHookTypes = [];
|
|
187
269
|
instance.devToolsHookSuppressionDepth = 0;
|
|
188
|
-
currentRuntime = runtime;
|
|
189
|
-
currentInstance = instance;
|
|
270
|
+
hookRenderState.currentRuntime = runtime;
|
|
271
|
+
hookRenderState.currentInstance = instance;
|
|
190
272
|
try {
|
|
191
|
-
return
|
|
273
|
+
return withContextReadObserver((context, value) => {
|
|
274
|
+
(instance.contextDependencies ??= new Map()).set(context, value);
|
|
275
|
+
}, render);
|
|
192
276
|
}
|
|
193
277
|
finally {
|
|
194
|
-
currentRuntime = previousRuntime;
|
|
195
|
-
currentInstance = previousInstance;
|
|
278
|
+
hookRenderState.currentRuntime = previousRuntime;
|
|
279
|
+
hookRenderState.currentInstance = previousInstance;
|
|
196
280
|
}
|
|
197
281
|
}
|
|
282
|
+
export function hasChangedContextDependency(runtime, keys) {
|
|
283
|
+
for (const key of keys) {
|
|
284
|
+
const dependencies = runtime.instances.get(key)?.contextDependencies;
|
|
285
|
+
if (dependencies === undefined) {
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
for (const [context, value] of dependencies) {
|
|
289
|
+
if (!Object.is(readContextValue(context), value)) {
|
|
290
|
+
return true;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
export function hasContextDependency(runtime, keys) {
|
|
297
|
+
return keys.some((key) => runtime.instances.get(key)?.contextDependencies !== undefined);
|
|
298
|
+
}
|
|
198
299
|
export function getDevToolsHookState(runtime, path) {
|
|
199
300
|
const instance = runtime.instances.get(path);
|
|
200
301
|
if (instance === undefined) {
|
|
@@ -214,10 +315,44 @@ export function renderWithStrictMode(runtime, render) {
|
|
|
214
315
|
runtime.strictModeDepth -= 1;
|
|
215
316
|
}
|
|
216
317
|
}
|
|
318
|
+
export function renderWithStrictModeMemoCapture(runtime, render) {
|
|
319
|
+
const previousCapture = runtime.strictMemoCapture;
|
|
320
|
+
const previousCaptureByHook = runtime.strictMemoCaptureByHook;
|
|
321
|
+
runtime.strictMemoCapture = [];
|
|
322
|
+
runtime.strictMemoCaptureByHook = new Map();
|
|
323
|
+
try {
|
|
324
|
+
const result = renderWithStrictMode(runtime, render);
|
|
325
|
+
return {
|
|
326
|
+
result,
|
|
327
|
+
memoValues: runtime.strictMemoCapture,
|
|
328
|
+
memoValuesByHook: runtime.strictMemoCaptureByHook,
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
finally {
|
|
332
|
+
runtime.strictMemoCapture = previousCapture;
|
|
333
|
+
runtime.strictMemoCaptureByHook = previousCaptureByHook;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
export function renderStrictModeReplay(runtime, memoValues, memoValuesByHook, render) {
|
|
337
|
+
const previousReplay = runtime.strictMemoReplay;
|
|
338
|
+
const previousReplayByHook = runtime.strictMemoReplayByHook;
|
|
339
|
+
runtime.strictReplayDepth += 1;
|
|
340
|
+
runtime.strictMemoReplay = { values: memoValues, index: 0 };
|
|
341
|
+
runtime.strictMemoReplayByHook = memoValuesByHook;
|
|
342
|
+
try {
|
|
343
|
+
return render();
|
|
344
|
+
}
|
|
345
|
+
finally {
|
|
346
|
+
runtime.strictMemoReplay = previousReplay;
|
|
347
|
+
runtime.strictMemoReplayByHook = previousReplayByHook;
|
|
348
|
+
runtime.strictReplayDepth -= 1;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
217
351
|
export function takeRuntimeSnapshot(runtime) {
|
|
218
352
|
return {
|
|
219
353
|
instanceKeys: new Set(runtime.instances.keys()),
|
|
220
354
|
portalContainers: new Set(runtime.portalContainers),
|
|
355
|
+
portalNodes: clonePortalNodes(runtime.portalNodes),
|
|
221
356
|
pendingInsertionEffectsLength: runtime.pendingInsertionEffects.length,
|
|
222
357
|
pendingLayoutEffectsLength: runtime.pendingLayoutEffects.length,
|
|
223
358
|
pendingEffectsLength: runtime.pendingEffects.length,
|
|
@@ -227,6 +362,11 @@ export function takeRuntimeSnapshot(runtime) {
|
|
|
227
362
|
identifierPrefix: runtime.identifierPrefix,
|
|
228
363
|
idMode: runtime.idMode,
|
|
229
364
|
strictModeDepth: runtime.strictModeDepth,
|
|
365
|
+
strictReplayDepth: runtime.strictReplayDepth,
|
|
366
|
+
strictMemoCapture: runtime.strictMemoCapture,
|
|
367
|
+
strictMemoCaptureByHook: runtime.strictMemoCaptureByHook,
|
|
368
|
+
strictMemoReplay: runtime.strictMemoReplay,
|
|
369
|
+
strictMemoReplayByHook: runtime.strictMemoReplayByHook,
|
|
230
370
|
profilerFlushDepth: runtime.profilerFlushDepth,
|
|
231
371
|
};
|
|
232
372
|
}
|
|
@@ -240,21 +380,49 @@ export function restoreRuntimeSnapshot(runtime, snapshot) {
|
|
|
240
380
|
runtime.identifierPrefix = snapshot.identifierPrefix;
|
|
241
381
|
runtime.idMode = snapshot.idMode;
|
|
242
382
|
runtime.strictModeDepth = snapshot.strictModeDepth;
|
|
383
|
+
runtime.strictReplayDepth = snapshot.strictReplayDepth;
|
|
384
|
+
runtime.strictMemoCapture = snapshot.strictMemoCapture;
|
|
385
|
+
runtime.strictMemoCaptureByHook = snapshot.strictMemoCaptureByHook;
|
|
386
|
+
runtime.strictMemoReplay = snapshot.strictMemoReplay;
|
|
387
|
+
runtime.strictMemoReplayByHook = snapshot.strictMemoReplayByHook;
|
|
243
388
|
runtime.profilerFlushDepth = snapshot.profilerFlushDepth;
|
|
244
389
|
for (const key of runtime.instances.keys()) {
|
|
245
390
|
if (!snapshot.instanceKeys.has(key)) {
|
|
246
391
|
runtime.instances.delete(key);
|
|
247
392
|
}
|
|
248
393
|
}
|
|
249
|
-
|
|
250
|
-
if (!snapshot.portalContainers.has(container)) {
|
|
251
|
-
container.replaceChildren();
|
|
252
|
-
}
|
|
253
|
-
}
|
|
394
|
+
clearRuntimePortalNodesExcept(runtime, snapshot.portalNodes);
|
|
254
395
|
runtime.portalContainers.clear();
|
|
255
396
|
for (const container of snapshot.portalContainers) {
|
|
256
397
|
runtime.portalContainers.add(container);
|
|
257
398
|
}
|
|
399
|
+
runtime.portalNodes = clonePortalNodes(snapshot.portalNodes);
|
|
400
|
+
}
|
|
401
|
+
export function clearRuntimePortalNodes(runtime) {
|
|
402
|
+
for (const [container, nodes] of runtime.portalNodes) {
|
|
403
|
+
for (const node of nodes) {
|
|
404
|
+
removeChildIfPresent(container, node);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
runtime.portalNodes.clear();
|
|
408
|
+
runtime.portalContainers.clear();
|
|
409
|
+
}
|
|
410
|
+
function clearRuntimePortalNodesExcept(runtime, preserved) {
|
|
411
|
+
for (const [container, nodes] of runtime.portalNodes) {
|
|
412
|
+
const preservedNodes = preserved.get(container);
|
|
413
|
+
for (const node of nodes) {
|
|
414
|
+
if (preservedNodes?.has(node) !== true) {
|
|
415
|
+
removeChildIfPresent(container, node);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
function clonePortalNodes(source) {
|
|
421
|
+
const clone = new Map();
|
|
422
|
+
for (const [container, nodes] of source) {
|
|
423
|
+
clone.set(container, new Set(nodes));
|
|
424
|
+
}
|
|
425
|
+
return clone;
|
|
258
426
|
}
|
|
259
427
|
export function useState(initial) {
|
|
260
428
|
const runtime = requireRuntime();
|
|
@@ -273,13 +441,22 @@ export function useState(initial) {
|
|
|
273
441
|
throw new Error("Hook order changed between renders.");
|
|
274
442
|
}
|
|
275
443
|
const setState = (value) => {
|
|
444
|
+
const previousValue = slot.value;
|
|
276
445
|
const nextValue = typeof value === "function"
|
|
277
446
|
? value(slot.value)
|
|
278
447
|
: value;
|
|
279
448
|
if (Object.is(slot.value, nextValue)) {
|
|
280
449
|
return;
|
|
281
450
|
}
|
|
451
|
+
if (hookRenderState.hostCommitDepth > 0 && !Object.hasOwn(slot, "hostCommitValue")) {
|
|
452
|
+
slot.hostCommitValue = previousValue;
|
|
453
|
+
}
|
|
282
454
|
slot.value = nextValue;
|
|
455
|
+
if (hookRenderState.hostCommitDepth > 0) {
|
|
456
|
+
updateHostCommitDirtyState(instance);
|
|
457
|
+
hookRenderState.queuedHostCommitRerenders.add(runtime);
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
283
460
|
scheduleInstanceUpdate(runtime, instance);
|
|
284
461
|
};
|
|
285
462
|
recordDevToolsHook("useState", {
|
|
@@ -349,6 +526,7 @@ export function useImperativeHandle(ref, create, deps) {
|
|
|
349
526
|
: { kind: "imperative-handle", deps });
|
|
350
527
|
}
|
|
351
528
|
export function useMemo(factory, deps) {
|
|
529
|
+
const runtime = requireRuntime();
|
|
352
530
|
const instance = requireInstance();
|
|
353
531
|
const index = instance.hookIndex;
|
|
354
532
|
instance.hookIndex += 1;
|
|
@@ -356,21 +534,72 @@ export function useMemo(factory, deps) {
|
|
|
356
534
|
if (slot !== undefined && slot.kind !== "memo") {
|
|
357
535
|
throw new Error("Hook order changed between renders.");
|
|
358
536
|
}
|
|
359
|
-
|
|
537
|
+
let value;
|
|
538
|
+
const shouldRecompute = slot === undefined ||
|
|
360
539
|
deps === undefined ||
|
|
361
540
|
slot.deps === undefined ||
|
|
362
|
-
!areHookInputsEqual(deps, slot.deps)
|
|
363
|
-
|
|
541
|
+
!areHookInputsEqual(deps, slot.deps);
|
|
542
|
+
if (runtime.strictReplayDepth > 0) {
|
|
543
|
+
const replayValue = factory();
|
|
544
|
+
if (slot === undefined) {
|
|
545
|
+
slot =
|
|
546
|
+
deps === undefined
|
|
547
|
+
? { kind: "memo", value: replayValue }
|
|
548
|
+
: { kind: "memo", value: replayValue, deps };
|
|
549
|
+
instance.hooks[index] = slot;
|
|
550
|
+
}
|
|
551
|
+
const hookKey = getStrictMemoHookKey(instance, index);
|
|
552
|
+
const replayByHook = runtime.strictMemoReplayByHook;
|
|
553
|
+
const replay = runtime.strictMemoReplay;
|
|
554
|
+
value = replayByHook?.has(hookKey) === true
|
|
555
|
+
? replayByHook.get(hookKey)
|
|
556
|
+
: replay === undefined || replay.index >= replay.values.length
|
|
557
|
+
? slot.value
|
|
558
|
+
: replay.values[replay.index++];
|
|
559
|
+
}
|
|
560
|
+
else if (shouldRecompute) {
|
|
561
|
+
value = factory();
|
|
364
562
|
slot =
|
|
365
563
|
deps === undefined
|
|
366
564
|
? { kind: "memo", value }
|
|
367
565
|
: { kind: "memo", value, deps };
|
|
368
566
|
instance.hooks[index] = slot;
|
|
369
567
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
568
|
+
else {
|
|
569
|
+
value = slot.value;
|
|
570
|
+
}
|
|
571
|
+
if (runtime.strictModeDepth > 0 && runtime.strictReplayDepth === 0) {
|
|
572
|
+
runtime.strictMemoCapture?.push(value);
|
|
573
|
+
runtime.strictMemoCaptureByHook?.set(getStrictMemoHookKey(instance, index), value);
|
|
574
|
+
}
|
|
575
|
+
const memoSlot = slot;
|
|
576
|
+
if (memoSlot === undefined) {
|
|
577
|
+
throw new Error("Hook order changed between renders.");
|
|
578
|
+
}
|
|
579
|
+
recordDevToolsHook("useMemo", memoSlot.deps === undefined
|
|
580
|
+
? { kind: "memo", value }
|
|
581
|
+
: { kind: "memo", value, deps: memoSlot.deps });
|
|
582
|
+
return value;
|
|
583
|
+
}
|
|
584
|
+
function getStrictMemoHookKey(instance, index) {
|
|
585
|
+
return `${instance.path}:${getStrictMemoOwnerId(instance.owner)}:${index}`;
|
|
586
|
+
}
|
|
587
|
+
function getStrictMemoOwnerId(owner) {
|
|
588
|
+
if ((typeof owner === "object" && owner !== null) || typeof owner === "function") {
|
|
589
|
+
const objectOwner = owner;
|
|
590
|
+
let ownerId = strictMemoObjectOwnerIds.get(objectOwner);
|
|
591
|
+
if (ownerId === undefined) {
|
|
592
|
+
ownerId = strictMemoOwnerId++;
|
|
593
|
+
strictMemoObjectOwnerIds.set(objectOwner, ownerId);
|
|
594
|
+
}
|
|
595
|
+
return ownerId;
|
|
596
|
+
}
|
|
597
|
+
let ownerId = strictMemoPrimitiveOwnerIds.get(owner);
|
|
598
|
+
if (ownerId === undefined) {
|
|
599
|
+
ownerId = strictMemoOwnerId++;
|
|
600
|
+
strictMemoPrimitiveOwnerIds.set(owner, ownerId);
|
|
601
|
+
}
|
|
602
|
+
return ownerId;
|
|
374
603
|
}
|
|
375
604
|
function assignRef(ref, value) {
|
|
376
605
|
if (typeof ref === "function") {
|
|
@@ -382,7 +611,7 @@ function assignRef(ref, value) {
|
|
|
382
611
|
}
|
|
383
612
|
}
|
|
384
613
|
function recordDevToolsHook(type, value) {
|
|
385
|
-
const instance = currentInstance;
|
|
614
|
+
const instance = hookRenderState.currentInstance;
|
|
386
615
|
if (instance === undefined || instance.devToolsHookSuppressionDepth > 0) {
|
|
387
616
|
return;
|
|
388
617
|
}
|
|
@@ -479,14 +708,29 @@ export function useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot =
|
|
|
479
708
|
recordExternalStoreCheck(getSnapshot, currentSnapshot);
|
|
480
709
|
runWithoutDevToolsHookTracking(() => useEffect(() => {
|
|
481
710
|
const checkForUpdates = () => {
|
|
711
|
+
if (instance.disposed === true) {
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
482
714
|
const nextSnapshot = getSnapshot();
|
|
483
715
|
if (!Object.is(slot.value, nextSnapshot)) {
|
|
484
716
|
slot.value = nextSnapshot;
|
|
717
|
+
instance.dirty = true;
|
|
718
|
+
runtime.externalStoreUpdate = true;
|
|
719
|
+
if (runtime.profilerFlushDepth > 0) {
|
|
720
|
+
hookRenderState.queuedEffectFlushRerenders.add(runtime);
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
485
723
|
runtime.rerender("sync");
|
|
486
724
|
}
|
|
487
725
|
};
|
|
488
|
-
|
|
489
|
-
|
|
726
|
+
if (slot.hasMounted !== true) {
|
|
727
|
+
checkForUpdates();
|
|
728
|
+
}
|
|
729
|
+
const unsubscribe = subscribe(checkForUpdates);
|
|
730
|
+
slot.hasMounted = true;
|
|
731
|
+
return () => {
|
|
732
|
+
unsubscribe();
|
|
733
|
+
};
|
|
490
734
|
}, [subscribe, getSnapshot]));
|
|
491
735
|
recordDevToolsHook("useSyncExternalStore", {
|
|
492
736
|
kind: "store",
|
|
@@ -617,280 +861,6 @@ export function unstable_useCacheRefresh() {
|
|
|
617
861
|
export function hasStableExternalStores(runtime) {
|
|
618
862
|
return runtime.externalStoreChecks.every((check) => Object.is(check.getSnapshot(), check.value));
|
|
619
863
|
}
|
|
620
|
-
export function renderToString(component, props, options = {}) {
|
|
621
|
-
const runtime = createRootRuntime(() => undefined, {
|
|
622
|
-
...options,
|
|
623
|
-
idMode: "server",
|
|
624
|
-
});
|
|
625
|
-
return runWithCacheScope(createCacheScope(), () => {
|
|
626
|
-
try {
|
|
627
|
-
const rendered = renderWithRootRuntime(runtime, "0", () => {
|
|
628
|
-
if (isClassComponentType(component)) {
|
|
629
|
-
const instance = new component(props);
|
|
630
|
-
return instance.render();
|
|
631
|
-
}
|
|
632
|
-
return component(props);
|
|
633
|
-
});
|
|
634
|
-
return typeof rendered === "string"
|
|
635
|
-
? rendered
|
|
636
|
-
: renderNodeToString(rendered, runtime, "0");
|
|
637
|
-
}
|
|
638
|
-
finally {
|
|
639
|
-
runtime.dispose();
|
|
640
|
-
}
|
|
641
|
-
});
|
|
642
|
-
}
|
|
643
|
-
function renderNodeToString(node, runtime, path) {
|
|
644
|
-
if (node === null || node === undefined || typeof node === "boolean") {
|
|
645
|
-
return "";
|
|
646
|
-
}
|
|
647
|
-
if (typeof node === "string" || typeof node === "number") {
|
|
648
|
-
return escapeHtml(node);
|
|
649
|
-
}
|
|
650
|
-
if (Array.isArray(node)) {
|
|
651
|
-
return node.map((child, index) => renderNodeToString(child, runtime, `${path}.${index}`)).join("");
|
|
652
|
-
}
|
|
653
|
-
if (!isReactCompatElement(node)) {
|
|
654
|
-
return "";
|
|
655
|
-
}
|
|
656
|
-
return renderElementToString(node, runtime, path);
|
|
657
|
-
}
|
|
658
|
-
function renderElementToString(element, runtime, path) {
|
|
659
|
-
if (typeof element.type === "string") {
|
|
660
|
-
if (element.type === "textarea") {
|
|
661
|
-
return renderTextareaToString(element, runtime, path);
|
|
662
|
-
}
|
|
663
|
-
if (element.type === "select") {
|
|
664
|
-
return renderSelectToString(element, runtime, path);
|
|
665
|
-
}
|
|
666
|
-
const attributes = element.type === "input"
|
|
667
|
-
? renderInputAttributesToString(element.props)
|
|
668
|
-
: Object.entries(element.props)
|
|
669
|
-
.map(([name, value]) => renderHtmlAttribute(name, value))
|
|
670
|
-
.filter((attribute) => attribute !== "")
|
|
671
|
-
.join("");
|
|
672
|
-
if (voidHtmlElements.has(element.type)) {
|
|
673
|
-
return `<${element.type}${attributes}/>`;
|
|
674
|
-
}
|
|
675
|
-
return `<${element.type}${attributes}>${renderNodeToString(element.props.children, runtime, `${path}.children`)}</${element.type}>`;
|
|
676
|
-
}
|
|
677
|
-
if (element.type === Fragment) {
|
|
678
|
-
return renderNodeToString(element.props.children, runtime, `${path}.fragment`);
|
|
679
|
-
}
|
|
680
|
-
if (element.type === Activity) {
|
|
681
|
-
if (element.props.mode === "hidden") {
|
|
682
|
-
return "";
|
|
683
|
-
}
|
|
684
|
-
return `<!--&-->${renderNodeToString(element.props.children, runtime, `${path}.activity`)}<!--/&-->`;
|
|
685
|
-
}
|
|
686
|
-
if (element.type === Profiler) {
|
|
687
|
-
return renderNodeToString(element.props.children, runtime, `${path}.profiler`);
|
|
688
|
-
}
|
|
689
|
-
if (isReactCompatProvider(element.type)) {
|
|
690
|
-
return renderWithContextProvider(element.type, element.props.value, () => renderNodeToString(element.props.children, runtime, `${path}.provider`));
|
|
691
|
-
}
|
|
692
|
-
if (isReactCompatConsumer(element.type)) {
|
|
693
|
-
const children = element.props.children;
|
|
694
|
-
if (typeof children === "function") {
|
|
695
|
-
return renderNodeToString(children(useContext(element.type.context)), runtime, `${path}.consumer`);
|
|
696
|
-
}
|
|
697
|
-
return "";
|
|
698
|
-
}
|
|
699
|
-
if (isForwardRefType(element.type)) {
|
|
700
|
-
const forwardRefType = element.type;
|
|
701
|
-
return renderNodeToString(renderWithRootRuntime(runtime, `${path}.forwardRef`, () => forwardRefType.render(element.props, element.ref)), runtime, `${path}.forwardRef`);
|
|
702
|
-
}
|
|
703
|
-
if (isMemoType(element.type)) {
|
|
704
|
-
return renderNodeToString({
|
|
705
|
-
...element,
|
|
706
|
-
type: element.type.type,
|
|
707
|
-
}, runtime, `${path}.memo`);
|
|
708
|
-
}
|
|
709
|
-
if (isClassComponentType(element.type)) {
|
|
710
|
-
const instance = new element.type(element.props);
|
|
711
|
-
return renderNodeToString(renderWithRootRuntime(runtime, path, () => instance.render()), runtime, path);
|
|
712
|
-
}
|
|
713
|
-
if (typeof element.type === "function") {
|
|
714
|
-
const component = element.type;
|
|
715
|
-
return renderNodeToString(renderWithRootRuntime(runtime, path, () => component(element.props)), runtime, path);
|
|
716
|
-
}
|
|
717
|
-
return "";
|
|
718
|
-
}
|
|
719
|
-
function isClassComponentType(value) {
|
|
720
|
-
return (typeof value === "function" &&
|
|
721
|
-
typeof value.prototype?.render === "function");
|
|
722
|
-
}
|
|
723
|
-
function renderTextareaToString(element, runtime, path) {
|
|
724
|
-
const value = element.props.value ??
|
|
725
|
-
element.props.defaultValue ??
|
|
726
|
-
element.props.children;
|
|
727
|
-
const attributes = Object.entries(element.props)
|
|
728
|
-
.filter(([name]) => name !== "value" && name !== "defaultValue")
|
|
729
|
-
.map(([name, child]) => renderHtmlAttribute(name, child))
|
|
730
|
-
.filter((attribute) => attribute !== "")
|
|
731
|
-
.join("");
|
|
732
|
-
return `<textarea${attributes}>${renderNodeToString(value, runtime, `${path}.textarea`)}</textarea>`;
|
|
733
|
-
}
|
|
734
|
-
function renderSelectToString(element, runtime, path) {
|
|
735
|
-
const selectedValue = element.props.value ??
|
|
736
|
-
element.props.defaultValue;
|
|
737
|
-
const attributes = Object.entries(element.props)
|
|
738
|
-
.filter(([name]) => name !== "value" && name !== "defaultValue")
|
|
739
|
-
.map(([name, child]) => renderHtmlAttribute(name, child))
|
|
740
|
-
.filter((attribute) => attribute !== "")
|
|
741
|
-
.join("");
|
|
742
|
-
return `<select${attributes}>${renderSelectChildrenToString(element.props.children, selectedValue, runtime, `${path}.select`)}</select>`;
|
|
743
|
-
}
|
|
744
|
-
function renderSelectChildrenToString(children, selectedValue, runtime, path) {
|
|
745
|
-
const childArray = Array.isArray(children) ? children : [children];
|
|
746
|
-
return childArray.map((child, index) => {
|
|
747
|
-
if (!isReactCompatElement(child) || child.type !== "option") {
|
|
748
|
-
return renderNodeToString(child, runtime, `${path}.${index}`);
|
|
749
|
-
}
|
|
750
|
-
const optionValue = child.props.value ?? child.props.children;
|
|
751
|
-
const selected = selectedValue !== undefined && String(optionValue) === String(selectedValue);
|
|
752
|
-
const props = selected
|
|
753
|
-
? { ...child.props, selected: true }
|
|
754
|
-
: child.props;
|
|
755
|
-
return renderElementToString({ ...child, props }, runtime, `${path}.${index}`);
|
|
756
|
-
}).join("");
|
|
757
|
-
}
|
|
758
|
-
function renderInputAttributesToString(props) {
|
|
759
|
-
const hasValue = props.value !== undefined;
|
|
760
|
-
const hasChecked = props.checked !== undefined;
|
|
761
|
-
return Object.entries(props)
|
|
762
|
-
.filter(([name]) => !((name === "defaultValue" && hasValue) || (name === "defaultChecked" && hasChecked)))
|
|
763
|
-
.sort(([leftName], [rightName]) => Number(isInputValueAttribute(leftName)) - Number(isInputValueAttribute(rightName)))
|
|
764
|
-
.map(([name, value]) => renderHtmlAttribute(toInputHtmlAttributeName(name), value))
|
|
765
|
-
.filter((attribute) => attribute !== "")
|
|
766
|
-
.join("");
|
|
767
|
-
}
|
|
768
|
-
function renderHtmlAttribute(name, value) {
|
|
769
|
-
if (name === "children" ||
|
|
770
|
-
name === "key" ||
|
|
771
|
-
name === "ref" ||
|
|
772
|
-
/^on[A-Z]/.test(name) ||
|
|
773
|
-
value === null ||
|
|
774
|
-
value === undefined ||
|
|
775
|
-
value === false ||
|
|
776
|
-
typeof value === "function") {
|
|
777
|
-
return "";
|
|
778
|
-
}
|
|
779
|
-
if (name === "style") {
|
|
780
|
-
const style = renderStyleAttribute(value);
|
|
781
|
-
return style === "" ? "" : ` style="${escapeHtml(style)}"`;
|
|
782
|
-
}
|
|
783
|
-
const attributeName = toHtmlAttributeName(name);
|
|
784
|
-
if (isDangerousHtmlAttribute(attributeName)) {
|
|
785
|
-
return isDangerousHtmlOptIn(value)
|
|
786
|
-
? ` ${attributeName}="${escapeHtml(value.__html)}"`
|
|
787
|
-
: "";
|
|
788
|
-
}
|
|
789
|
-
if (typeof value === "object") {
|
|
790
|
-
return "";
|
|
791
|
-
}
|
|
792
|
-
if (value === true) {
|
|
793
|
-
return ` ${attributeName}=""`;
|
|
794
|
-
}
|
|
795
|
-
return ` ${attributeName}="${escapeHtml(value)}"`;
|
|
796
|
-
}
|
|
797
|
-
function isInputValueAttribute(name) {
|
|
798
|
-
return name === "value" || name === "defaultValue";
|
|
799
|
-
}
|
|
800
|
-
function toInputHtmlAttributeName(name) {
|
|
801
|
-
if (name === "defaultValue") {
|
|
802
|
-
return "value";
|
|
803
|
-
}
|
|
804
|
-
if (name === "defaultChecked") {
|
|
805
|
-
return "checked";
|
|
806
|
-
}
|
|
807
|
-
return name;
|
|
808
|
-
}
|
|
809
|
-
function toHtmlAttributeName(name) {
|
|
810
|
-
return HTML_ATTRIBUTE_ALIASES[name] ?? name;
|
|
811
|
-
}
|
|
812
|
-
const HTML_ATTRIBUTE_ALIASES = {
|
|
813
|
-
acceptCharset: "accept-charset",
|
|
814
|
-
autoFocus: "autofocus",
|
|
815
|
-
autoPlay: "autoplay",
|
|
816
|
-
charSet: "charset",
|
|
817
|
-
className: "class",
|
|
818
|
-
colSpan: "colspan",
|
|
819
|
-
contentEditable: "contenteditable",
|
|
820
|
-
crossOrigin: "crossorigin",
|
|
821
|
-
encType: "enctype",
|
|
822
|
-
formAction: "formaction",
|
|
823
|
-
frameBorder: "frameborder",
|
|
824
|
-
htmlFor: "for",
|
|
825
|
-
httpEquiv: "http-equiv",
|
|
826
|
-
maxLength: "maxlength",
|
|
827
|
-
minLength: "minlength",
|
|
828
|
-
noValidate: "novalidate",
|
|
829
|
-
playsInline: "playsinline",
|
|
830
|
-
readOnly: "readOnly",
|
|
831
|
-
rowSpan: "rowspan",
|
|
832
|
-
spellCheck: "spellcheck",
|
|
833
|
-
srcDoc: "srcdoc",
|
|
834
|
-
srcSet: "srcset",
|
|
835
|
-
tabIndex: "tabindex",
|
|
836
|
-
useMap: "usemap",
|
|
837
|
-
};
|
|
838
|
-
function renderStyleAttribute(value) {
|
|
839
|
-
if (typeof value !== "object" || value === null) {
|
|
840
|
-
return "";
|
|
841
|
-
}
|
|
842
|
-
return Object.entries(value)
|
|
843
|
-
.filter(([, propertyValue]) => propertyValue !== null &&
|
|
844
|
-
propertyValue !== undefined &&
|
|
845
|
-
typeof propertyValue !== "boolean" &&
|
|
846
|
-
propertyValue !== "")
|
|
847
|
-
.map(([name, propertyValue]) => `${toKebabCase(name)}:${renderCssValue(name, propertyValue)}`)
|
|
848
|
-
.join(";");
|
|
849
|
-
}
|
|
850
|
-
function renderCssValue(name, value) {
|
|
851
|
-
if (typeof value !== "number" || value === 0 || isUnitlessCssProperty(name)) {
|
|
852
|
-
return String(value);
|
|
853
|
-
}
|
|
854
|
-
return `${value}px`;
|
|
855
|
-
}
|
|
856
|
-
function toKebabCase(value) {
|
|
857
|
-
return value.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
|
|
858
|
-
}
|
|
859
|
-
function isUnitlessCssProperty(name) {
|
|
860
|
-
return (name === "flex" ||
|
|
861
|
-
name === "fontWeight" ||
|
|
862
|
-
name === "lineHeight" ||
|
|
863
|
-
name === "opacity" ||
|
|
864
|
-
name === "order" ||
|
|
865
|
-
name === "zIndex" ||
|
|
866
|
-
name === "zoom");
|
|
867
|
-
}
|
|
868
|
-
const voidHtmlElements = new Set([
|
|
869
|
-
"area",
|
|
870
|
-
"base",
|
|
871
|
-
"br",
|
|
872
|
-
"col",
|
|
873
|
-
"embed",
|
|
874
|
-
"hr",
|
|
875
|
-
"img",
|
|
876
|
-
"input",
|
|
877
|
-
"link",
|
|
878
|
-
"meta",
|
|
879
|
-
"param",
|
|
880
|
-
"source",
|
|
881
|
-
"track",
|
|
882
|
-
"wbr",
|
|
883
|
-
]);
|
|
884
|
-
function isForwardRefType(value) {
|
|
885
|
-
return (typeof value === "object" &&
|
|
886
|
-
value !== null &&
|
|
887
|
-
value.$$typeof === FORWARD_REF_TYPE);
|
|
888
|
-
}
|
|
889
|
-
function isMemoType(value) {
|
|
890
|
-
return (typeof value === "object" &&
|
|
891
|
-
value !== null &&
|
|
892
|
-
value.$$typeof === MEMO_TYPE);
|
|
893
|
-
}
|
|
894
864
|
function readThenable(thenable) {
|
|
895
865
|
const record = thenable;
|
|
896
866
|
if (record.status === "fulfilled") {
|
|
@@ -957,6 +927,15 @@ export function flushSyncUpdates(callback) {
|
|
|
957
927
|
currentEventPriority = previousEventPriority;
|
|
958
928
|
}
|
|
959
929
|
}
|
|
930
|
+
export function runWithHostCommit(callback) {
|
|
931
|
+
hookRenderState.hostCommitDepth += 1;
|
|
932
|
+
try {
|
|
933
|
+
return callback();
|
|
934
|
+
}
|
|
935
|
+
finally {
|
|
936
|
+
hookRenderState.hostCommitDepth -= 1;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
960
939
|
export function useTransition() {
|
|
961
940
|
const [pending, setPending] = runWithoutDevToolsHookTracking(() => useState(false));
|
|
962
941
|
const startTransitionWithPending = (scope) => {
|
|
@@ -1070,6 +1049,7 @@ function useEffectImpl(effectKind, callback, deps) {
|
|
|
1070
1049
|
throw new Error("Hook order changed between renders.");
|
|
1071
1050
|
}
|
|
1072
1051
|
const shouldRun = slot === undefined ||
|
|
1052
|
+
slot.mounted !== true ||
|
|
1073
1053
|
deps === undefined ||
|
|
1074
1054
|
slot.deps === undefined ||
|
|
1075
1055
|
!areHookInputsEqual(deps, slot.deps);
|
|
@@ -1092,7 +1072,8 @@ function useEffectImpl(effectKind, callback, deps) {
|
|
|
1092
1072
|
}
|
|
1093
1073
|
}
|
|
1094
1074
|
slot.strictReplay =
|
|
1095
|
-
runtime.strictModeDepth > 0
|
|
1075
|
+
(runtime.strictModeDepth > 0 || runtime.strictReplayDepth > 0) &&
|
|
1076
|
+
effectKind !== "insertion";
|
|
1096
1077
|
if (shouldRun) {
|
|
1097
1078
|
const queue = effectKind === "insertion"
|
|
1098
1079
|
? runtime.pendingInsertionEffects
|
|
@@ -1103,7 +1084,7 @@ function useEffectImpl(effectKind, callback, deps) {
|
|
|
1103
1084
|
}
|
|
1104
1085
|
}
|
|
1105
1086
|
function recordExternalStoreCheck(getSnapshot, value) {
|
|
1106
|
-
currentRuntime?.externalStoreChecks.push({ getSnapshot, value });
|
|
1087
|
+
hookRenderState.currentRuntime?.externalStoreChecks.push({ getSnapshot, value });
|
|
1107
1088
|
}
|
|
1108
1089
|
function flushPendingEffects(queue) {
|
|
1109
1090
|
const pending = queue.splice(0);
|
|
@@ -1121,6 +1102,7 @@ function flushPendingEffects(queue) {
|
|
|
1121
1102
|
else {
|
|
1122
1103
|
delete slot.cleanup;
|
|
1123
1104
|
}
|
|
1105
|
+
slot.mounted = true;
|
|
1124
1106
|
if (shouldReplay) {
|
|
1125
1107
|
strictReplay.push({ slot });
|
|
1126
1108
|
}
|
|
@@ -1184,9 +1166,20 @@ function runActionStateDispatch(slot, runtime, instance, payload) {
|
|
|
1184
1166
|
});
|
|
1185
1167
|
}
|
|
1186
1168
|
function scheduleInstanceUpdate(runtime, instance) {
|
|
1169
|
+
if (instance.disposed === true) {
|
|
1170
|
+
return;
|
|
1171
|
+
}
|
|
1187
1172
|
instance.dirty = true;
|
|
1188
1173
|
if (transitionDepth === 0) {
|
|
1189
1174
|
syncVersion += 1;
|
|
1175
|
+
if (hookRenderState.hostCommitDepth > 0) {
|
|
1176
|
+
hookRenderState.queuedHostCommitRerenders.add(runtime);
|
|
1177
|
+
return;
|
|
1178
|
+
}
|
|
1179
|
+
if (runtime.effectFlushPhase !== undefined) {
|
|
1180
|
+
hookRenderState.queuedEffectFlushRerenders.add(runtime);
|
|
1181
|
+
return;
|
|
1182
|
+
}
|
|
1190
1183
|
if (eventBatchDepth > 0) {
|
|
1191
1184
|
queueEventRerender(runtime);
|
|
1192
1185
|
return;
|
|
@@ -1198,6 +1191,58 @@ function scheduleInstanceUpdate(runtime, instance) {
|
|
|
1198
1191
|
queueTransitionRerender(runtime, currentTransitionContext);
|
|
1199
1192
|
}
|
|
1200
1193
|
}
|
|
1194
|
+
function flushHostCommitRerenders() {
|
|
1195
|
+
if (hookRenderState.hostCommitDepth > 0 ||
|
|
1196
|
+
hookRenderState.queuedHostCommitRerenders.size === 0) {
|
|
1197
|
+
return;
|
|
1198
|
+
}
|
|
1199
|
+
const runtimes = [...hookRenderState.queuedHostCommitRerenders];
|
|
1200
|
+
hookRenderState.queuedHostCommitRerenders.clear();
|
|
1201
|
+
for (const runtime of runtimes) {
|
|
1202
|
+
const hasDirtyInstance = Array.from(runtime.instances.values()).some((instance) => instance.dirty);
|
|
1203
|
+
clearHostCommitStateBaselines(runtime);
|
|
1204
|
+
if (hasDirtyInstance) {
|
|
1205
|
+
runtime.rerender("sync");
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
function flushEffectFlushRerenders() {
|
|
1210
|
+
if (effectFlushRerenderDepth > 0 ||
|
|
1211
|
+
hookRenderState.queuedEffectFlushRerenders.size === 0) {
|
|
1212
|
+
return;
|
|
1213
|
+
}
|
|
1214
|
+
effectFlushRerenderDepth += 1;
|
|
1215
|
+
try {
|
|
1216
|
+
for (let attempt = 0; attempt < 3 && hookRenderState.queuedEffectFlushRerenders.size > 0; attempt += 1) {
|
|
1217
|
+
const runtimes = [...hookRenderState.queuedEffectFlushRerenders];
|
|
1218
|
+
hookRenderState.queuedEffectFlushRerenders.clear();
|
|
1219
|
+
for (const runtime of runtimes) {
|
|
1220
|
+
const hasDirtyInstance = Array.from(runtime.instances.values()).some((instance) => instance.dirty);
|
|
1221
|
+
if (hasDirtyInstance) {
|
|
1222
|
+
runtime.rerender("sync");
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
hookRenderState.queuedEffectFlushRerenders.clear();
|
|
1227
|
+
}
|
|
1228
|
+
finally {
|
|
1229
|
+
effectFlushRerenderDepth -= 1;
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
function updateHostCommitDirtyState(instance) {
|
|
1233
|
+
instance.dirty = instance.hooks.some((slot) => slot.kind === "state" &&
|
|
1234
|
+
Object.hasOwn(slot, "hostCommitValue") &&
|
|
1235
|
+
!Object.is(slot.hostCommitValue, slot.value));
|
|
1236
|
+
}
|
|
1237
|
+
function clearHostCommitStateBaselines(runtime) {
|
|
1238
|
+
for (const instance of runtime.instances.values()) {
|
|
1239
|
+
for (const slot of instance.hooks) {
|
|
1240
|
+
if (slot.kind === "state") {
|
|
1241
|
+
delete slot.hostCommitValue;
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1201
1246
|
function getCacheLeaf(scope, callback, args) {
|
|
1202
1247
|
let node = scope.functionCaches.get(callback);
|
|
1203
1248
|
if (node === undefined) {
|
|
@@ -1233,7 +1278,7 @@ function createCacheTrieNode() {
|
|
|
1233
1278
|
};
|
|
1234
1279
|
}
|
|
1235
1280
|
function getCurrentCacheScope() {
|
|
1236
|
-
return currentCacheScope ?? getGlobalCacheScope();
|
|
1281
|
+
return hookRenderState.currentCacheScope ?? getGlobalCacheScope();
|
|
1237
1282
|
}
|
|
1238
1283
|
function getGlobalCacheScope() {
|
|
1239
1284
|
return globalThis[CACHE_SCOPE_SYMBOL];
|
|
@@ -1265,25 +1310,27 @@ function cleanupInactiveInstances(runtime) {
|
|
|
1265
1310
|
}
|
|
1266
1311
|
}
|
|
1267
1312
|
function cleanupInstance(instance) {
|
|
1313
|
+
instance.disposed = true;
|
|
1268
1314
|
for (const slot of instance.hooks) {
|
|
1269
1315
|
if (slot?.kind === "effect") {
|
|
1270
1316
|
slot.disposed = true;
|
|
1317
|
+
slot.mounted = false;
|
|
1271
1318
|
slot.cleanup?.();
|
|
1272
1319
|
delete slot.cleanup;
|
|
1273
1320
|
}
|
|
1274
1321
|
}
|
|
1275
1322
|
}
|
|
1276
1323
|
function requireRuntime() {
|
|
1277
|
-
if (currentRuntime === undefined) {
|
|
1324
|
+
if (hookRenderState.currentRuntime === undefined) {
|
|
1278
1325
|
throw new Error("Hooks can only be called while rendering.");
|
|
1279
1326
|
}
|
|
1280
|
-
return currentRuntime;
|
|
1327
|
+
return hookRenderState.currentRuntime;
|
|
1281
1328
|
}
|
|
1282
1329
|
function requireInstance() {
|
|
1283
|
-
if (currentInstance === undefined) {
|
|
1330
|
+
if (hookRenderState.currentInstance === undefined) {
|
|
1284
1331
|
throw new Error("Hooks can only be called while rendering.");
|
|
1285
1332
|
}
|
|
1286
|
-
return currentInstance;
|
|
1333
|
+
return hookRenderState.currentInstance;
|
|
1287
1334
|
}
|
|
1288
1335
|
function areHookInputsEqual(nextDeps, previousDeps) {
|
|
1289
1336
|
if (nextDeps.length !== previousDeps.length) {
|