@reckona/mreact-compat 0.0.159 → 0.0.161
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/dist/class-component.d.ts +5 -0
- package/dist/class-component.d.ts.map +1 -1
- package/dist/class-component.js +36 -11
- package/dist/class-component.js.map +1 -1
- package/dist/context.d.ts +4 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +4 -0
- package/dist/context.js.map +1 -1
- package/dist/element.d.ts +28 -0
- package/dist/element.d.ts.map +1 -1
- package/dist/element.js +21 -1
- package/dist/element.js.map +1 -1
- package/dist/event-priority.d.ts +1 -0
- package/dist/event-priority.d.ts.map +1 -1
- package/dist/event-priority.js +1 -0
- package/dist/event-priority.js.map +1 -1
- package/dist/event-replay.d.ts +6 -0
- package/dist/event-replay.d.ts.map +1 -1
- package/dist/event-replay.js +4 -0
- package/dist/event-replay.js.map +1 -1
- package/dist/flight-decoder.d.ts +1 -0
- package/dist/flight-decoder.d.ts.map +1 -1
- package/dist/flight-decoder.js.map +1 -1
- package/dist/flight-protocol.d.ts +2 -0
- package/dist/flight-protocol.d.ts.map +1 -1
- package/dist/flight-protocol.js +1 -0
- package/dist/flight-protocol.js.map +1 -1
- package/dist/flight-types.d.ts +21 -0
- package/dist/flight-types.d.ts.map +1 -1
- package/dist/flight-types.js.map +1 -1
- package/dist/flight.d.ts +7 -0
- package/dist/flight.d.ts.map +1 -1
- package/dist/flight.js +5 -0
- package/dist/flight.js.map +1 -1
- package/dist/hooks-entry.d.ts +2 -0
- package/dist/hooks-entry.d.ts.map +1 -1
- package/dist/hooks-entry.js +1 -0
- package/dist/hooks-entry.js.map +1 -1
- package/dist/hooks.d.ts +36 -0
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +42 -10
- package/dist/hooks.js.map +1 -1
- package/dist/host-reconciler.js +30 -30
- package/dist/host-reconciler.js.map +1 -1
- package/dist/hydration.d.ts +2 -0
- package/dist/hydration.d.ts.map +1 -1
- package/dist/hydration.js +1 -0
- package/dist/hydration.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +1 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +1 -0
- package/dist/internal.js.map +1 -1
- package/dist/jsx-dev-runtime.d.ts +5 -0
- package/dist/jsx-dev-runtime.d.ts.map +1 -1
- package/dist/jsx-dev-runtime.js +3 -0
- package/dist/jsx-dev-runtime.js.map +1 -1
- package/dist/jsx-runtime.d.ts +13 -0
- package/dist/jsx-runtime.d.ts.map +1 -1
- package/dist/jsx-runtime.js +4 -0
- package/dist/jsx-runtime.js.map +1 -1
- package/dist/react-default.d.ts +2 -0
- package/dist/react-default.d.ts.map +1 -1
- package/dist/react-default.js +2 -0
- package/dist/react-default.js.map +1 -1
- package/dist/root.d.ts +13 -0
- package/dist/root.d.ts.map +1 -1
- package/dist/root.js +6 -0
- package/dist/root.js.map +1 -1
- package/dist/scheduler.d.ts +23 -0
- package/dist/scheduler.d.ts.map +1 -1
- package/dist/scheduler.js +19 -0
- package/dist/scheduler.js.map +1 -1
- package/dist/server-render.d.ts +1 -0
- package/dist/server-render.d.ts.map +1 -1
- package/dist/server-render.js +1 -0
- package/dist/server-render.js.map +1 -1
- package/package.json +3 -3
- package/src/class-component.ts +47 -11
- package/src/context.ts +4 -0
- package/src/element.ts +33 -6
- package/src/event-priority.ts +1 -0
- package/src/event-replay.ts +6 -0
- package/src/flight-decoder.ts +1 -0
- package/src/flight-protocol.ts +2 -0
- package/src/flight-types.ts +21 -0
- package/src/flight.ts +7 -0
- package/src/hooks-entry.ts +2 -0
- package/src/hooks.ts +55 -15
- package/src/host-reconciler.ts +39 -38
- package/src/hydration.ts +2 -0
- package/src/index.ts +3 -0
- package/src/internal.ts +1 -0
- package/src/jsx-dev-runtime.ts +5 -0
- package/src/jsx-runtime.ts +13 -0
- package/src/react-default.ts +2 -0
- package/src/root.ts +13 -0
- package/src/scheduler.ts +23 -0
- package/src/server-render.ts +1 -0
package/src/hooks.ts
CHANGED
|
@@ -92,6 +92,7 @@ interface ExternalStoreCheck {
|
|
|
92
92
|
value: unknown;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
/** Cache scope that stores memoized cache() results and cancellation state. */
|
|
95
96
|
export interface CacheScope {
|
|
96
97
|
functionCaches: WeakMap<(...args: never[]) => unknown, CacheTrieNode>;
|
|
97
98
|
controller: AbortController;
|
|
@@ -194,6 +195,7 @@ let strictMemoOwnerId = 0;
|
|
|
194
195
|
const strictMemoObjectOwnerIds = new WeakMap<object, number>();
|
|
195
196
|
const queuedTransitionRerenders = new Map<RootRuntime, TransitionContext>();
|
|
196
197
|
const queuedEventRerenders = new Set<RootRuntime>();
|
|
198
|
+
/** React version string matched by the compatibility layer. */
|
|
197
199
|
export const version = "19.2.6";
|
|
198
200
|
|
|
199
201
|
export interface ReactiveTextBinding {
|
|
@@ -204,6 +206,7 @@ export interface ReactiveTextBinding {
|
|
|
204
206
|
const reactiveTextBindingsByNode = new WeakMap<Text, ReactiveTextBinding>();
|
|
205
207
|
const hydratedIdsByRuntime = new WeakMap<RootRuntime, Map<string, string>>();
|
|
206
208
|
|
|
209
|
+
/** Flushes React-compatible updates produced inside a test interaction. */
|
|
207
210
|
export function act<T>(callback: () => T): T extends PromiseLike<unknown> ? Promise<void> : void {
|
|
208
211
|
const previousPriority = currentEventPriority;
|
|
209
212
|
currentEventPriority = "discrete";
|
|
@@ -267,6 +270,7 @@ function flushActWork(): void {
|
|
|
267
270
|
flushEffectFlushRerenders();
|
|
268
271
|
}
|
|
269
272
|
|
|
273
|
+
/** Priority category used while batching an event callback. */
|
|
270
274
|
export type EventPriority = "discrete" | "continuous" | "default";
|
|
271
275
|
export type RenderPriority = "sync" | "transition" | "continuous";
|
|
272
276
|
|
|
@@ -406,6 +410,7 @@ export function createRootRuntime(
|
|
|
406
410
|
};
|
|
407
411
|
}
|
|
408
412
|
|
|
413
|
+
/** Creates an isolated cache scope for cache() and cacheSignal(). */
|
|
409
414
|
export function createCacheScope(): CacheScope {
|
|
410
415
|
return {
|
|
411
416
|
functionCaches: new WeakMap(),
|
|
@@ -414,12 +419,14 @@ export function createCacheScope(): CacheScope {
|
|
|
414
419
|
};
|
|
415
420
|
}
|
|
416
421
|
|
|
422
|
+
/** Clears a cache scope and aborts work tied to its previous signal. */
|
|
417
423
|
export function refreshCacheScope(scope: CacheScope): void {
|
|
418
424
|
scope.controller.abort();
|
|
419
425
|
scope.functionCaches = new WeakMap();
|
|
420
426
|
scope.controller = new AbortController();
|
|
421
427
|
}
|
|
422
428
|
|
|
429
|
+
/** Runs a callback with a cache scope active for nested cache() calls. */
|
|
423
430
|
export function runWithCacheScope<T>(scope: CacheScope, callback: () => T): T {
|
|
424
431
|
const previousScope = hookRenderState.currentCacheScope;
|
|
425
432
|
const previousGlobalScope = getGlobalCacheScope();
|
|
@@ -756,6 +763,7 @@ function clonePortalNodes(source: Map<Element, Set<Node>>): Map<Element, Set<Nod
|
|
|
756
763
|
return clone;
|
|
757
764
|
}
|
|
758
765
|
|
|
766
|
+
/** Stores component-local state and returns the current value with an updater. */
|
|
759
767
|
export function useState<T>(
|
|
760
768
|
initial: T | (() => T),
|
|
761
769
|
): [T, (value: T | ((previous: T) => T)) => void] {
|
|
@@ -904,6 +912,7 @@ function isReactiveTextBinding(value: unknown): value is ReactiveTextBinding {
|
|
|
904
912
|
);
|
|
905
913
|
}
|
|
906
914
|
|
|
915
|
+
/** Stores reducer-managed component state and returns the current state with a dispatch function. */
|
|
907
916
|
export function useReducer<TState, TAction, TInitial = TState>(
|
|
908
917
|
reducer: (state: TState, action: TAction) => TState,
|
|
909
918
|
initialArg: TInitial,
|
|
@@ -940,6 +949,7 @@ export function useReducer<TState, TAction, TInitial = TState>(
|
|
|
940
949
|
return [state, dispatchRef.current];
|
|
941
950
|
}
|
|
942
951
|
|
|
952
|
+
/** Returns a stable mutable ref object for the component instance. */
|
|
943
953
|
export function useRef<T>(initial: T): { current: T } {
|
|
944
954
|
const instance = requireInstance();
|
|
945
955
|
const index = instance.hookIndex;
|
|
@@ -964,6 +974,7 @@ export function useRef<T>(initial: T): { current: T } {
|
|
|
964
974
|
return slot.value as { current: T };
|
|
965
975
|
}
|
|
966
976
|
|
|
977
|
+
/** Returns a stable id string that matches server and client rendering. */
|
|
967
978
|
export function useId(): string {
|
|
968
979
|
const runtime = requireRuntime();
|
|
969
980
|
const instance = requireInstance();
|
|
@@ -1000,6 +1011,7 @@ export function useId(): string {
|
|
|
1000
1011
|
return idRef.current;
|
|
1001
1012
|
}
|
|
1002
1013
|
|
|
1014
|
+
/** Assigns a custom imperative handle to a forwarded ref. */
|
|
1003
1015
|
export function useImperativeHandle<T>(
|
|
1004
1016
|
ref: unknown,
|
|
1005
1017
|
create: () => T,
|
|
@@ -1019,6 +1031,7 @@ export function useImperativeHandle<T>(
|
|
|
1019
1031
|
: { kind: "imperative-handle", deps });
|
|
1020
1032
|
}
|
|
1021
1033
|
|
|
1034
|
+
/** Memoizes a computed value until its dependency list changes. */
|
|
1022
1035
|
export function useMemo<T>(factory: () => T, deps?: readonly unknown[]): T {
|
|
1023
1036
|
const runtime = requireRuntime();
|
|
1024
1037
|
const instance = requireInstance();
|
|
@@ -1159,6 +1172,7 @@ function runWithoutDevToolsHookTracking<T>(callback: () => T): T {
|
|
|
1159
1172
|
}
|
|
1160
1173
|
}
|
|
1161
1174
|
|
|
1175
|
+
/** Memoizes a callback reference until its dependency list changes. */
|
|
1162
1176
|
export function useCallback<T extends (...args: never[]) => unknown>(
|
|
1163
1177
|
callback: T,
|
|
1164
1178
|
deps?: readonly unknown[],
|
|
@@ -1170,6 +1184,7 @@ export function useCallback<T extends (...args: never[]) => unknown>(
|
|
|
1170
1184
|
return value;
|
|
1171
1185
|
}
|
|
1172
1186
|
|
|
1187
|
+
/** Records a value for React DevTools hook inspection. */
|
|
1173
1188
|
export function useDebugValue(_value: unknown, _format?: (value: unknown) => unknown): void {
|
|
1174
1189
|
const instance = requireInstance();
|
|
1175
1190
|
const index = instance.hookIndex;
|
|
@@ -1199,6 +1214,7 @@ export function useDebugValue(_value: unknown, _format?: (value: unknown) => unk
|
|
|
1199
1214
|
});
|
|
1200
1215
|
}
|
|
1201
1216
|
|
|
1217
|
+
/** Creates a stable event callback that always calls the latest implementation. */
|
|
1202
1218
|
export function useEffectEvent<TArgs extends unknown[], TResult>(
|
|
1203
1219
|
callback: (...args: TArgs) => TResult,
|
|
1204
1220
|
): (...args: TArgs) => TResult {
|
|
@@ -1216,6 +1232,7 @@ export function useEffectEvent<TArgs extends unknown[], TResult>(
|
|
|
1216
1232
|
return event;
|
|
1217
1233
|
}
|
|
1218
1234
|
|
|
1235
|
+
/** Runs an effect after the rendered output has been committed. */
|
|
1219
1236
|
export function useEffect(
|
|
1220
1237
|
callback: EffectCallback,
|
|
1221
1238
|
deps?: readonly unknown[],
|
|
@@ -1226,6 +1243,7 @@ export function useEffect(
|
|
|
1226
1243
|
: { kind: "effect", effectKind: "normal", deps });
|
|
1227
1244
|
}
|
|
1228
1245
|
|
|
1246
|
+
/** Runs an insertion effect before layout effects are flushed. */
|
|
1229
1247
|
export function useInsertionEffect(
|
|
1230
1248
|
callback: EffectCallback,
|
|
1231
1249
|
deps?: readonly unknown[],
|
|
@@ -1236,6 +1254,7 @@ export function useInsertionEffect(
|
|
|
1236
1254
|
: { kind: "effect", effectKind: "insertion", deps });
|
|
1237
1255
|
}
|
|
1238
1256
|
|
|
1257
|
+
/** Runs a layout effect after DOM mutations and before normal effects. */
|
|
1239
1258
|
export function useLayoutEffect(
|
|
1240
1259
|
callback: EffectCallback,
|
|
1241
1260
|
deps?: readonly unknown[],
|
|
@@ -1246,6 +1265,7 @@ export function useLayoutEffect(
|
|
|
1246
1265
|
: { kind: "effect", effectKind: "layout", deps });
|
|
1247
1266
|
}
|
|
1248
1267
|
|
|
1268
|
+
/** Subscribes to an external store with snapshot checks for consistent rendering. */
|
|
1249
1269
|
export function useSyncExternalStore<T>(
|
|
1250
1270
|
subscribe: (listener: () => void) => () => void,
|
|
1251
1271
|
getSnapshot: () => T,
|
|
@@ -1321,6 +1341,7 @@ export function useSyncExternalStore<T>(
|
|
|
1321
1341
|
return slot.value as T;
|
|
1322
1342
|
}
|
|
1323
1343
|
|
|
1344
|
+
/** Tracks state and pending status for an action that receives the previous state. */
|
|
1324
1345
|
export function useActionState<TState, TPayload>(
|
|
1325
1346
|
action: (previousState: TState, payload: TPayload) => TState | Promise<TState>,
|
|
1326
1347
|
initialState: TState,
|
|
@@ -1369,6 +1390,7 @@ export function useActionState<TState, TPayload>(
|
|
|
1369
1390
|
];
|
|
1370
1391
|
}
|
|
1371
1392
|
|
|
1393
|
+
/** Returns an optimistic state value and dispatcher layered on top of a base state. */
|
|
1372
1394
|
export function useOptimistic<TState, TPayload>(
|
|
1373
1395
|
state: TState,
|
|
1374
1396
|
update?: (state: TState, payload: TPayload) => TState,
|
|
@@ -1419,6 +1441,7 @@ export function useOptimistic<TState, TPayload>(
|
|
|
1419
1441
|
return [slot.optimisticState as TState, slot.dispatch as (payload: TPayload) => void];
|
|
1420
1442
|
}
|
|
1421
1443
|
|
|
1444
|
+
/** Reads a context-like value or suspends on a thenable until it resolves. */
|
|
1422
1445
|
export function use<T>(usable: PromiseLike<T> | unknown): T {
|
|
1423
1446
|
if (isReactCompatContext(usable)) {
|
|
1424
1447
|
return useContext(usable) as T;
|
|
@@ -1431,6 +1454,7 @@ export function use<T>(usable: PromiseLike<T> | unknown): T {
|
|
|
1431
1454
|
return usable as T;
|
|
1432
1455
|
}
|
|
1433
1456
|
|
|
1457
|
+
/** Memoizes a function within the currently active cache scope. */
|
|
1434
1458
|
export function cache<TArgs extends unknown[], TResult>(
|
|
1435
1459
|
callback: (...args: TArgs) => TResult,
|
|
1436
1460
|
): (...args: TArgs) => TResult {
|
|
@@ -1464,15 +1488,18 @@ export function cache<TArgs extends unknown[], TResult>(
|
|
|
1464
1488
|
};
|
|
1465
1489
|
}
|
|
1466
1490
|
|
|
1491
|
+
/** Returns the abort signal for the currently active cache scope. */
|
|
1467
1492
|
export function cacheSignal(): AbortSignal | null {
|
|
1468
1493
|
return getCurrentCacheScope()?.controller.signal ?? null;
|
|
1469
1494
|
}
|
|
1470
1495
|
|
|
1496
|
+
/** Returns the current owner stack captured for cache diagnostics. */
|
|
1471
1497
|
export function captureOwnerStack(): string | null {
|
|
1472
1498
|
const stack = getCurrentCacheScope()?.ownerStack ?? emptyCacheOwnerStack;
|
|
1473
1499
|
return stack.length === 0 ? null : stack.join("\n");
|
|
1474
1500
|
}
|
|
1475
1501
|
|
|
1502
|
+
/** Returns a callback placeholder for refreshing the current cache boundary. */
|
|
1476
1503
|
export function unstable_useCacheRefresh(): () => void {
|
|
1477
1504
|
return useCallback(() => undefined, []);
|
|
1478
1505
|
}
|
|
@@ -1521,9 +1548,12 @@ function readThenable<T>(thenable: PromiseLike<T>): T {
|
|
|
1521
1548
|
throw thenable;
|
|
1522
1549
|
}
|
|
1523
1550
|
|
|
1551
|
+
/** Callback body scheduled as transition work. */
|
|
1524
1552
|
export type TransitionScope = () => void;
|
|
1553
|
+
/** Function that schedules a transition scope. */
|
|
1525
1554
|
export type StartTransition = (scope: TransitionScope) => void;
|
|
1526
1555
|
|
|
1556
|
+
/** Schedules non-urgent updates produced inside a transition scope. */
|
|
1527
1557
|
export function startTransition(scope: TransitionScope): void {
|
|
1528
1558
|
const context = {
|
|
1529
1559
|
syncVersion,
|
|
@@ -1533,6 +1563,7 @@ export function startTransition(scope: TransitionScope): void {
|
|
|
1533
1563
|
runTransitionScope(scope, context);
|
|
1534
1564
|
}
|
|
1535
1565
|
|
|
1566
|
+
/** Runs a callback while updates are batched at the requested event priority. */
|
|
1536
1567
|
export function runWithEventPriority<T>(
|
|
1537
1568
|
priority: EventPriority,
|
|
1538
1569
|
callback: () => T,
|
|
@@ -1583,6 +1614,7 @@ export function runWithHostCommit<T>(callback: () => T): T {
|
|
|
1583
1614
|
}
|
|
1584
1615
|
}
|
|
1585
1616
|
|
|
1617
|
+
/** Returns transition pending state and a function that starts transition work. */
|
|
1586
1618
|
export function useTransition(): [boolean, StartTransition] {
|
|
1587
1619
|
const instance = requireInstance();
|
|
1588
1620
|
const [pending, setPending] = runWithoutDevToolsHookTracking(() => useState(false));
|
|
@@ -1623,6 +1655,7 @@ export function useTransition(): [boolean, StartTransition] {
|
|
|
1623
1655
|
];
|
|
1624
1656
|
}
|
|
1625
1657
|
|
|
1658
|
+
/** Defers a value update so urgent renders can commit first. */
|
|
1626
1659
|
export function useDeferredValue<T>(value: T, initialValue?: T): T {
|
|
1627
1660
|
const [deferredValue, setDeferredValue] = runWithoutDevToolsHookTracking(() =>
|
|
1628
1661
|
useState(arguments.length > 1 ? (initialValue as T) : value)
|
|
@@ -1929,24 +1962,10 @@ function runActionStateDispatch(
|
|
|
1929
1962
|
);
|
|
1930
1963
|
}
|
|
1931
1964
|
|
|
1932
|
-
function
|
|
1965
|
+
export function scheduleRuntimeRerender(
|
|
1933
1966
|
runtime: RootRuntime,
|
|
1934
|
-
instance: ComponentInstance,
|
|
1935
1967
|
options: { deferSync?: boolean } = {},
|
|
1936
1968
|
): void {
|
|
1937
|
-
if (instance.disposed === true) {
|
|
1938
|
-
return;
|
|
1939
|
-
}
|
|
1940
|
-
|
|
1941
|
-
instance.dirty = true;
|
|
1942
|
-
if (
|
|
1943
|
-
hookRenderState.currentRuntime === runtime &&
|
|
1944
|
-
hookRenderState.currentInstance === instance
|
|
1945
|
-
) {
|
|
1946
|
-
runtime.renderPhaseUpdate = true;
|
|
1947
|
-
return;
|
|
1948
|
-
}
|
|
1949
|
-
|
|
1950
1969
|
if (transitionDepth === 0) {
|
|
1951
1970
|
syncVersion += 1;
|
|
1952
1971
|
if (hookRenderState.hostCommitDepth > 0) {
|
|
@@ -1974,6 +1993,27 @@ function scheduleInstanceUpdate(
|
|
|
1974
1993
|
}
|
|
1975
1994
|
}
|
|
1976
1995
|
|
|
1996
|
+
function scheduleInstanceUpdate(
|
|
1997
|
+
runtime: RootRuntime,
|
|
1998
|
+
instance: ComponentInstance,
|
|
1999
|
+
options: { deferSync?: boolean } = {},
|
|
2000
|
+
): void {
|
|
2001
|
+
if (instance.disposed === true) {
|
|
2002
|
+
return;
|
|
2003
|
+
}
|
|
2004
|
+
|
|
2005
|
+
instance.dirty = true;
|
|
2006
|
+
if (
|
|
2007
|
+
hookRenderState.currentRuntime === runtime &&
|
|
2008
|
+
hookRenderState.currentInstance === instance
|
|
2009
|
+
) {
|
|
2010
|
+
runtime.renderPhaseUpdate = true;
|
|
2011
|
+
return;
|
|
2012
|
+
}
|
|
2013
|
+
|
|
2014
|
+
scheduleRuntimeRerender(runtime, options);
|
|
2015
|
+
}
|
|
2016
|
+
|
|
1977
2017
|
function flushHostCommitRerenders(): void {
|
|
1978
2018
|
if (
|
|
1979
2019
|
hookRenderState.hostCommitDepth > 0 ||
|
package/src/host-reconciler.ts
CHANGED
|
@@ -1207,7 +1207,7 @@ function createHostFiberImpl(
|
|
|
1207
1207
|
areMemoPropsEqual(memoType, previousMemoState.props, node.props)
|
|
1208
1208
|
) {
|
|
1209
1209
|
markActiveInstanceKeys(runtime, previousMemoState.instanceKeys);
|
|
1210
|
-
fiber.child = current
|
|
1210
|
+
fiber.child = getSkippedChild(current);
|
|
1211
1211
|
fiber.memoizedState = previousMemoState;
|
|
1212
1212
|
return { fiber, consumed: options.previousNodes?.length ?? 0 };
|
|
1213
1213
|
}
|
|
@@ -1317,6 +1317,8 @@ function createHostFiberImpl(
|
|
|
1317
1317
|
current?.tag === "class-component" && current.type === classType
|
|
1318
1318
|
? (current.stateNode as ClassComponentInstance)
|
|
1319
1319
|
: undefined;
|
|
1320
|
+
const hasCurrentClassFiber =
|
|
1321
|
+
current?.tag === "class-component" && current.type === classType;
|
|
1320
1322
|
const rendered = renderClassComponentWithRuntime(
|
|
1321
1323
|
classType,
|
|
1322
1324
|
node.props,
|
|
@@ -1331,12 +1333,13 @@ function createHostFiberImpl(
|
|
|
1331
1333
|
previousClassChildKeys,
|
|
1332
1334
|
`${path}.class`,
|
|
1333
1335
|
),
|
|
1336
|
+
allowSkip: hasCurrentClassFiber,
|
|
1334
1337
|
},
|
|
1335
1338
|
);
|
|
1336
1339
|
applyRef(node.ref, rendered.kind === "skip" ? current?.stateNode : rendered.instance);
|
|
1337
1340
|
|
|
1338
1341
|
if (rendered.kind === "skip") {
|
|
1339
|
-
fiber.child = current
|
|
1342
|
+
fiber.child = getSkippedChild(current);
|
|
1340
1343
|
return { fiber, consumed: options.previousNodes?.length ?? 0 };
|
|
1341
1344
|
}
|
|
1342
1345
|
|
|
@@ -1414,7 +1417,7 @@ function createHostFiberImpl(
|
|
|
1414
1417
|
!hasPendingAsyncChild(current?.child)
|
|
1415
1418
|
) {
|
|
1416
1419
|
markActiveInstanceKeys(runtime, previousFunctionState.instanceKeys);
|
|
1417
|
-
fiber.child = current
|
|
1420
|
+
fiber.child = getSkippedChild(current);
|
|
1418
1421
|
fiber.memoizedState = current?.memoizedState;
|
|
1419
1422
|
fiber.stateNode = previousFunctionState;
|
|
1420
1423
|
return { fiber, consumed: options.previousNodes?.length ?? 0 };
|
|
@@ -1651,6 +1654,18 @@ function commitHostDirtyFiber(
|
|
|
1651
1654
|
if (directTextChild !== undefined) {
|
|
1652
1655
|
const text = syncDirectHostTextChild(element, directTextChild);
|
|
1653
1656
|
subscribeReactiveHostTextBinding(props, text);
|
|
1657
|
+
} else if (
|
|
1658
|
+
fiber.hostChildListChanged ||
|
|
1659
|
+
fiber.childListChanged ||
|
|
1660
|
+
fiber.subtreeChildListChanged
|
|
1661
|
+
) {
|
|
1662
|
+
const childNodes = commitHostChildren(fiber.child, element, eventRoot, `${path}.c`, options);
|
|
1663
|
+
if (
|
|
1664
|
+
!(childNodes.length === 0 && committedPortalContainers.has(element)) &&
|
|
1665
|
+
!shouldPreserveContentEditableChildren(element, props, childNodes)
|
|
1666
|
+
) {
|
|
1667
|
+
syncChildNodes(element, childNodes);
|
|
1668
|
+
}
|
|
1654
1669
|
} else if (fiber.subtreeFlags !== NoFlags) {
|
|
1655
1670
|
commitHostDirtyChildren(fiber.child, element, eventRoot, `${path}.c`, options);
|
|
1656
1671
|
}
|
|
@@ -1793,7 +1808,7 @@ function commitHostAppendSuffix(
|
|
|
1793
1808
|
path: string,
|
|
1794
1809
|
options: RenderOptions,
|
|
1795
1810
|
): boolean {
|
|
1796
|
-
const append =
|
|
1811
|
+
const append = getAppendSuffix(fiber.alternate?.child, fiber.child);
|
|
1797
1812
|
|
|
1798
1813
|
if (append === undefined) {
|
|
1799
1814
|
return false;
|
|
@@ -1813,39 +1828,6 @@ function commitHostAppendSuffix(
|
|
|
1813
1828
|
return true;
|
|
1814
1829
|
}
|
|
1815
1830
|
|
|
1816
|
-
function getPlacementAppendSuffix(next: Fiber | undefined): { fiber: Fiber; index: number } | undefined {
|
|
1817
|
-
let nextCursor = next;
|
|
1818
|
-
let index = 0;
|
|
1819
|
-
|
|
1820
|
-
while (nextCursor !== undefined) {
|
|
1821
|
-
if ((nextCursor.flags & Placement) !== NoFlags) {
|
|
1822
|
-
if (index === 0) {
|
|
1823
|
-
return undefined;
|
|
1824
|
-
}
|
|
1825
|
-
|
|
1826
|
-
let appendCursor: Fiber | undefined = nextCursor;
|
|
1827
|
-
|
|
1828
|
-
while (appendCursor !== undefined) {
|
|
1829
|
-
if ((appendCursor.flags & Placement) === NoFlags) {
|
|
1830
|
-
return undefined;
|
|
1831
|
-
}
|
|
1832
|
-
appendCursor = appendCursor.sibling;
|
|
1833
|
-
}
|
|
1834
|
-
|
|
1835
|
-
return { fiber: nextCursor, index };
|
|
1836
|
-
}
|
|
1837
|
-
|
|
1838
|
-
if (hasHostCommitWork(nextCursor)) {
|
|
1839
|
-
return undefined;
|
|
1840
|
-
}
|
|
1841
|
-
|
|
1842
|
-
nextCursor = nextCursor.sibling;
|
|
1843
|
-
index += 1;
|
|
1844
|
-
}
|
|
1845
|
-
|
|
1846
|
-
return undefined;
|
|
1847
|
-
}
|
|
1848
|
-
|
|
1849
1831
|
function commitHostSingleRemoval(fiber: Fiber, parent: ParentNode): boolean {
|
|
1850
1832
|
const removed = getSingleRemovedFiber(fiber.alternate?.child, fiber.child);
|
|
1851
1833
|
|
|
@@ -1959,6 +1941,22 @@ function collectCommittedHostNodes(fiber: Fiber): Node[] {
|
|
|
1959
1941
|
return nodes;
|
|
1960
1942
|
}
|
|
1961
1943
|
|
|
1944
|
+
function getSkippedChild(current: Fiber | undefined): Fiber | undefined {
|
|
1945
|
+
const child = current?.child;
|
|
1946
|
+
const alternateChild = current?.alternate?.child;
|
|
1947
|
+
|
|
1948
|
+
if (
|
|
1949
|
+
child !== undefined &&
|
|
1950
|
+
alternateChild !== undefined &&
|
|
1951
|
+
collectCommittedHostNodes(child).length === 0 &&
|
|
1952
|
+
collectCommittedHostNodes(alternateChild).length > 0
|
|
1953
|
+
) {
|
|
1954
|
+
return alternateChild;
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
return child;
|
|
1958
|
+
}
|
|
1959
|
+
|
|
1962
1960
|
function finishHostPassthroughFiber(fiber: Fiber): void {
|
|
1963
1961
|
fiber.memoizedProps = fiber.pendingProps;
|
|
1964
1962
|
finishCommittedFiber(fiber);
|
|
@@ -2000,7 +1998,9 @@ function commitHostFiber(
|
|
|
2000
1998
|
fiber.hydrateExisting !== true &&
|
|
2001
1999
|
fiber.flags === NoFlags &&
|
|
2002
2000
|
fiber.subtreeFlags === NoFlags &&
|
|
2003
|
-
fiber.hostChildListChanged !== true
|
|
2001
|
+
fiber.hostChildListChanged !== true &&
|
|
2002
|
+
fiber.childListChanged !== true &&
|
|
2003
|
+
fiber.subtreeChildListChanged !== true
|
|
2004
2004
|
) {
|
|
2005
2005
|
fiber.memoizedProps = fiber.pendingProps;
|
|
2006
2006
|
return [element];
|
|
@@ -2045,6 +2045,7 @@ function commitHostFiber(
|
|
|
2045
2045
|
} else if (
|
|
2046
2046
|
fiber.hostChildListChanged ||
|
|
2047
2047
|
fiber.childListChanged ||
|
|
2048
|
+
fiber.subtreeChildListChanged ||
|
|
2048
2049
|
fiber.hydrateExisting === true ||
|
|
2049
2050
|
(fiber.subtreeFlags & Placement) !== NoFlags
|
|
2050
2051
|
) {
|
package/src/hydration.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ReactCompatNode } from "./element.js";
|
|
2
2
|
|
|
3
|
+
/** Details passed to recoverable hydration error callbacks. */
|
|
3
4
|
export interface HydrationRecoverableErrorInfo {
|
|
4
5
|
kind: "tag" | "text" | "attribute" | "node" | "suspense-server-error";
|
|
5
6
|
path: string;
|
|
@@ -27,6 +28,7 @@ export interface HydrationScope {
|
|
|
27
28
|
after: ChildNode | null;
|
|
28
29
|
}
|
|
29
30
|
|
|
31
|
+
/** Applies streamed out-of-order hydration fragments to their placeholders. */
|
|
30
32
|
export function applyStreamingHydrationFragments(
|
|
31
33
|
root: ParentNode = document,
|
|
32
34
|
): void {
|
package/src/index.ts
CHANGED
|
@@ -20,12 +20,14 @@ export {
|
|
|
20
20
|
lazy,
|
|
21
21
|
memo,
|
|
22
22
|
} from "./element.js";
|
|
23
|
+
/** Element and node types exported by the React-compatible root entrypoint. */
|
|
23
24
|
export type {
|
|
24
25
|
ErrorBoundaryOptions,
|
|
25
26
|
ElementType,
|
|
26
27
|
ReactCompatElement,
|
|
27
28
|
ReactCompatNode,
|
|
28
29
|
} from "./element.js";
|
|
30
|
+
/** DOM and form event types exported by the JSX runtime. */
|
|
29
31
|
export type {
|
|
30
32
|
FormEvent,
|
|
31
33
|
FormEventHandler,
|
|
@@ -93,4 +95,5 @@ export {
|
|
|
93
95
|
} from "./hooks.js";
|
|
94
96
|
export { renderChildToString, renderToString } from "./server-render.js";
|
|
95
97
|
export type { StartTransition, TransitionScope } from "./hooks.js";
|
|
98
|
+
/** Default React-compatible namespace export. */
|
|
96
99
|
export { default } from "./react-default.js";
|
package/src/internal.ts
CHANGED
package/src/jsx-dev-runtime.ts
CHANGED
|
@@ -13,8 +13,11 @@ import type {
|
|
|
13
13
|
JSXIntrinsicElements,
|
|
14
14
|
} from "./jsx-runtime.js";
|
|
15
15
|
|
|
16
|
+
/** Fragment marker used by the development JSX runtime. */
|
|
16
17
|
export { Fragment };
|
|
18
|
+
/** Metadata key used by compiled JSX for reactive text bindings. */
|
|
17
19
|
export { REACTIVE_TEXT_BINDING_META };
|
|
20
|
+
/** JSX event and attribute types re-exported by the development JSX runtime. */
|
|
18
21
|
export type {
|
|
19
22
|
FormEvent,
|
|
20
23
|
FormEventHandler,
|
|
@@ -25,6 +28,7 @@ export type {
|
|
|
25
28
|
JSXIntrinsicElements,
|
|
26
29
|
} from "./jsx-runtime.js";
|
|
27
30
|
|
|
31
|
+
/** JSX namespace exported by the development JSX runtime. */
|
|
28
32
|
export namespace JSX {
|
|
29
33
|
export interface Element extends ReactCompatElement {}
|
|
30
34
|
|
|
@@ -33,6 +37,7 @@ export namespace JSX {
|
|
|
33
37
|
export interface IntrinsicElements extends JSXIntrinsicElements {}
|
|
34
38
|
}
|
|
35
39
|
|
|
40
|
+
/** Creates a JSX element with development metadata arguments. */
|
|
36
41
|
export function jsxDEV<P extends Record<string, unknown>>(
|
|
37
42
|
type: ElementType<P>,
|
|
38
43
|
props: (P & { children?: ReactCompatNode; key?: unknown; ref?: unknown }) | null,
|
package/src/jsx-runtime.ts
CHANGED
|
@@ -9,9 +9,12 @@ import type {
|
|
|
9
9
|
ReactCompatNode,
|
|
10
10
|
} from "./element.js";
|
|
11
11
|
|
|
12
|
+
/** Fragment marker used by the automatic JSX runtime. */
|
|
12
13
|
export { Fragment };
|
|
14
|
+
/** Metadata key used by compiled JSX for reactive text bindings. */
|
|
13
15
|
export { REACTIVE_TEXT_BINDING_META };
|
|
14
16
|
|
|
17
|
+
/** DOM event type with a narrowed currentTarget. */
|
|
15
18
|
export type JSXEvent<
|
|
16
19
|
TCurrentTarget extends EventTarget,
|
|
17
20
|
TEvent extends Event = Event,
|
|
@@ -19,19 +22,23 @@ export type JSXEvent<
|
|
|
19
22
|
readonly currentTarget: TCurrentTarget;
|
|
20
23
|
};
|
|
21
24
|
|
|
25
|
+
/** Event handler type used by JSX DOM attributes. */
|
|
22
26
|
export type JSXEventHandler<
|
|
23
27
|
TCurrentTarget extends EventTarget,
|
|
24
28
|
TEvent extends Event = Event,
|
|
25
29
|
> = (event: JSXEvent<TCurrentTarget, TEvent>) => unknown;
|
|
26
30
|
|
|
31
|
+
/** Submit event type used by form-related JSX attributes. */
|
|
27
32
|
export type FormEvent<TCurrentTarget extends EventTarget = Element> = JSXEvent<
|
|
28
33
|
TCurrentTarget,
|
|
29
34
|
SubmitEvent
|
|
30
35
|
>;
|
|
31
36
|
|
|
37
|
+
/** Submit event handler type used by form-related JSX attributes. */
|
|
32
38
|
export type FormEventHandler<TCurrentTarget extends EventTarget = Element> =
|
|
33
39
|
JSXEventHandler<TCurrentTarget, SubmitEvent>;
|
|
34
40
|
|
|
41
|
+
/** DOM event attributes accepted by JSX elements. */
|
|
35
42
|
export interface JSXDOMAttributes<TElement extends EventTarget> {
|
|
36
43
|
children?: ReactCompatNode;
|
|
37
44
|
onClick?: JSXEventHandler<TElement, MouseEvent>;
|
|
@@ -40,16 +47,19 @@ export interface JSXDOMAttributes<TElement extends EventTarget> {
|
|
|
40
47
|
onSubmit?: JSXEventHandler<TElement, SubmitEvent>;
|
|
41
48
|
}
|
|
42
49
|
|
|
50
|
+
/** HTML attributes accepted by JSX host elements. */
|
|
43
51
|
export interface JSXHTMLAttributes<TElement extends HTMLElement>
|
|
44
52
|
extends JSXDOMAttributes<TElement> {
|
|
45
53
|
[attributeName: string]: unknown;
|
|
46
54
|
}
|
|
47
55
|
|
|
56
|
+
/** Attributes accepted by every JSX element. */
|
|
48
57
|
export interface JSXIntrinsicAttributes {
|
|
49
58
|
key?: unknown;
|
|
50
59
|
ref?: unknown;
|
|
51
60
|
}
|
|
52
61
|
|
|
62
|
+
/** Built-in JSX element names and their attribute types. */
|
|
53
63
|
export interface JSXIntrinsicElements {
|
|
54
64
|
form: JSXHTMLAttributes<HTMLFormElement> & {
|
|
55
65
|
onSubmit?: JSXEventHandler<HTMLFormElement, SubmitEvent>;
|
|
@@ -67,6 +77,7 @@ export interface JSXIntrinsicElements {
|
|
|
67
77
|
[elementName: string]: Record<string, unknown>;
|
|
68
78
|
}
|
|
69
79
|
|
|
80
|
+
/** JSX namespace exported by the automatic JSX runtime. */
|
|
70
81
|
export namespace JSX {
|
|
71
82
|
export interface Element extends ReactCompatElement {}
|
|
72
83
|
|
|
@@ -83,6 +94,7 @@ declare global {
|
|
|
83
94
|
}
|
|
84
95
|
}
|
|
85
96
|
|
|
97
|
+
/** Creates a single-child JSX element for the automatic JSX runtime. */
|
|
86
98
|
export function jsx<P extends Record<string, unknown>>(
|
|
87
99
|
type: ElementType<P>,
|
|
88
100
|
props: (P & { children?: ReactCompatNode; key?: unknown; ref?: unknown }) | null,
|
|
@@ -91,6 +103,7 @@ export function jsx<P extends Record<string, unknown>>(
|
|
|
91
103
|
return createElementFromJsx(type, props, key);
|
|
92
104
|
}
|
|
93
105
|
|
|
106
|
+
/** Creates a multi-child JSX element for the automatic JSX runtime. */
|
|
94
107
|
export function jsxs<P extends Record<string, unknown>>(
|
|
95
108
|
type: ElementType<P>,
|
|
96
109
|
props: (P & { children?: ReactCompatNode; key?: unknown; ref?: unknown }) | null,
|
package/src/react-default.ts
CHANGED
|
@@ -68,6 +68,7 @@ import {
|
|
|
68
68
|
} from "./hooks.js";
|
|
69
69
|
import { renderChildToString, renderToString } from "./server-render.js";
|
|
70
70
|
|
|
71
|
+
/** Default React-compatible namespace export. */
|
|
71
72
|
const ReactCompat = {
|
|
72
73
|
Component,
|
|
73
74
|
PureComponent,
|
|
@@ -131,4 +132,5 @@ const ReactCompat = {
|
|
|
131
132
|
version,
|
|
132
133
|
} as const;
|
|
133
134
|
|
|
135
|
+
/** Default React-compatible namespace export. */
|
|
134
136
|
export default ReactCompat;
|
package/src/root.ts
CHANGED
|
@@ -41,15 +41,18 @@ import {
|
|
|
41
41
|
import type { Fiber, FiberRoot } from "./fiber.js";
|
|
42
42
|
import { renderIntoContainer } from "./reconciler.js";
|
|
43
43
|
|
|
44
|
+
/** Root controller returned by createRoot and hydrateRoot. */
|
|
44
45
|
export interface Root {
|
|
45
46
|
render(element: ReactCompatNode): void;
|
|
46
47
|
unmount(): void;
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
/** Options used when creating a client render root. */
|
|
49
51
|
export interface RootOptions {
|
|
50
52
|
identifierPrefix?: string;
|
|
51
53
|
}
|
|
52
54
|
|
|
55
|
+
/** Options used when hydrating server-rendered markup. */
|
|
53
56
|
export interface HydrateRootOptions {
|
|
54
57
|
onRecoverableError?: (
|
|
55
58
|
error: Error,
|
|
@@ -60,11 +63,13 @@ export interface HydrateRootOptions {
|
|
|
60
63
|
identifierPrefix?: string;
|
|
61
64
|
}
|
|
62
65
|
|
|
66
|
+
/** Controller for deferred or selective streaming hydration. */
|
|
63
67
|
export interface StreamingHydrationRoot {
|
|
64
68
|
hydrate(element: ReactCompatNode, options?: HydrateRootOptions): Root;
|
|
65
69
|
dispose(): void;
|
|
66
70
|
}
|
|
67
71
|
|
|
72
|
+
/** Options for creating a streaming hydration root. */
|
|
68
73
|
export interface StreamingHydrationRootOptions {
|
|
69
74
|
manifest?: EventHydrationManifest;
|
|
70
75
|
manifestRoot?: ParentNode;
|
|
@@ -74,12 +79,14 @@ export interface StreamingHydrationRootOptions {
|
|
|
74
79
|
selectiveHydration?: SelectiveHydrationOptions;
|
|
75
80
|
}
|
|
76
81
|
|
|
82
|
+
/** Rules that choose which boundary to hydrate after a captured event. */
|
|
77
83
|
export interface SelectiveHydrationOptions {
|
|
78
84
|
element?: ReactCompatNode;
|
|
79
85
|
options?: HydrateRootOptions | ((event: Event) => HydrateRootOptions);
|
|
80
86
|
boundaries?: Record<string, SelectiveHydrationBoundary>;
|
|
81
87
|
}
|
|
82
88
|
|
|
89
|
+
/** Element and options used to hydrate one selective boundary. */
|
|
83
90
|
export interface SelectiveHydrationBoundary {
|
|
84
91
|
element: ReactCompatNode;
|
|
85
92
|
options?: HydrateRootOptions | ((event: Event) => HydrateRootOptions);
|
|
@@ -87,6 +94,7 @@ export interface SelectiveHydrationBoundary {
|
|
|
87
94
|
|
|
88
95
|
const legacyRoots = new WeakMap<Element, Root>();
|
|
89
96
|
|
|
97
|
+
/** Creates a root that renders React-compatible nodes into a DOM container. */
|
|
90
98
|
export function createRoot(
|
|
91
99
|
container: Element,
|
|
92
100
|
options: RootOptions = {},
|
|
@@ -236,16 +244,19 @@ function renderHydratingHostFiberIntoContainer(
|
|
|
236
244
|
throw new Error("Store unstable.");
|
|
237
245
|
}
|
|
238
246
|
|
|
247
|
+
/** Renders a React-compatible node into a legacy root container. */
|
|
239
248
|
export function render(element: ReactCompatNode, container: Element): void {
|
|
240
249
|
const root = legacyRoots.get(container) ?? createRoot(container);
|
|
241
250
|
legacyRoots.set(container, root);
|
|
242
251
|
root.render(element);
|
|
243
252
|
}
|
|
244
253
|
|
|
254
|
+
/** Runs updates synchronously and flushes pending reactive work before returning. */
|
|
245
255
|
export function flushSync<T>(callback: () => T): T {
|
|
246
256
|
return flushSyncUpdates(callback);
|
|
247
257
|
}
|
|
248
258
|
|
|
259
|
+
/** Hydrates server-rendered markup with a React-compatible element tree. */
|
|
249
260
|
export function hydrateRoot(
|
|
250
261
|
container: Element,
|
|
251
262
|
element: ReactCompatNode,
|
|
@@ -355,6 +366,7 @@ function laneForRenderPriority(priority: RenderPriority): Lane {
|
|
|
355
366
|
return SyncLane;
|
|
356
367
|
}
|
|
357
368
|
|
|
369
|
+
/** Creates a root that can hydrate streamed or selectively revealed markup. */
|
|
358
370
|
export function createStreamingHydrationRoot(
|
|
359
371
|
container: Element,
|
|
360
372
|
options: StreamingHydrationRootOptions = {},
|
|
@@ -434,6 +446,7 @@ export function createStreamingHydrationRoot(
|
|
|
434
446
|
};
|
|
435
447
|
}
|
|
436
448
|
|
|
449
|
+
/** Unmounts a legacy root from a container and reports whether anything was removed. */
|
|
437
450
|
export function unmountComponentAtNode(container: Element): boolean {
|
|
438
451
|
const root = legacyRoots.get(container);
|
|
439
452
|
|