test-renderer 0.14.0 → 0.16.0

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/index.js CHANGED
@@ -1,837 +1,580 @@
1
- var __defProp = Object.defineProperty;
2
- var __defProps = Object.defineProperties;
3
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
- var __spreadValues = (a, b) => {
9
- for (var prop in b || (b = {}))
10
- if (__hasOwnProp.call(b, prop))
11
- __defNormalProp(a, prop, b[prop]);
12
- if (__getOwnPropSymbols)
13
- for (var prop of __getOwnPropSymbols(b)) {
14
- if (__propIsEnum.call(b, prop))
15
- __defNormalProp(a, prop, b[prop]);
16
- }
17
- return a;
18
- };
19
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
- var __objRest = (source, exclude) => {
21
- var target = {};
22
- for (var prop in source)
23
- if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
24
- target[prop] = source[prop];
25
- if (source != null && __getOwnPropSymbols)
26
- for (var prop of __getOwnPropSymbols(source)) {
27
- if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
28
- target[prop] = source[prop];
29
- }
30
- return target;
31
- };
32
-
33
- // src/renderer.ts
34
- import { ConcurrentRoot } from "react-reconciler/constants";
35
-
36
- // src/constants.ts
37
- var Tag = {
38
- Container: "CONTAINER",
39
- Instance: "INSTANCE",
40
- Text: "TEXT"
1
+ import { ConcurrentRoot, DefaultEventPriority, NoEventPriority } from "react-reconciler/constants.js";
2
+ import ReactReconciler from "react-reconciler";
3
+ //#region src/constants.ts
4
+ const Tag = {
5
+ Container: "CONTAINER",
6
+ Instance: "INSTANCE",
7
+ Text: "TEXT"
41
8
  };
42
- var CONTAINER_TYPE = "";
43
-
44
- // src/query-all.ts
45
- function queryAll(element, predicate, options) {
46
- var _a, _b;
47
- const includeSelf = (_a = options == null ? void 0 : options.includeSelf) != null ? _a : false;
48
- const matchDeepestOnly = (_b = options == null ? void 0 : options.matchDeepestOnly) != null ? _b : false;
49
- const results = [];
50
- const matchingDescendants = [];
51
- element.children.forEach((child) => {
52
- if (typeof child === "string") {
53
- return;
54
- }
55
- matchingDescendants.push(...queryAll(child, predicate, __spreadProps(__spreadValues({}, options), { includeSelf: true })));
56
- });
57
- if (includeSelf && // When matchDeepestOnly = true: add current element only if no descendants match
58
- (matchingDescendants.length === 0 || !matchDeepestOnly) && predicate(element)) {
59
- results.push(element);
60
- }
61
- results.push(...matchingDescendants);
62
- return results;
9
+ //#endregion
10
+ //#region src/performance.ts
11
+ function mark(name, details) {
12
+ if (!globalThis.TEST_RENDERER_ENABLE_PROFILING) return;
13
+ performance.mark(`test-renderer/${name}`, { detail: details });
63
14
  }
64
-
65
- // src/render-to-json.ts
66
- function renderContainerToJson(instance) {
67
- return {
68
- type: CONTAINER_TYPE,
69
- props: {},
70
- children: renderChildrenToJson(instance.children),
71
- $$typeof: /* @__PURE__ */ Symbol.for("react.test.json")
72
- };
15
+ function measureStart(name) {
16
+ if (!globalThis.TEST_RENDERER_ENABLE_PROFILING) return;
17
+ performance.mark(`test-renderer/${name}:start`);
73
18
  }
74
- function renderInstanceToJson(instance) {
75
- if (instance.isHidden) {
76
- return null;
77
- }
78
- const _a = instance.props, { children: _children } = _a, restProps = __objRest(_a, ["children"]);
79
- return {
80
- type: instance.type,
81
- props: restProps,
82
- children: renderChildrenToJson(instance.children),
83
- $$typeof: /* @__PURE__ */ Symbol.for("react.test.json")
84
- };
19
+ function measureEnd(name, details) {
20
+ if (!globalThis.TEST_RENDERER_ENABLE_PROFILING) return;
21
+ performance.mark(`test-renderer/${name}:end`);
22
+ performance.measure(`test-renderer/${name}`, {
23
+ start: `test-renderer/${name}:start`,
24
+ end: `test-renderer/${name}:end`,
25
+ detail: details
26
+ });
85
27
  }
86
- function renderTextInstanceToJson(instance) {
87
- if (instance.isHidden) {
88
- return null;
89
- }
90
- return instance.text;
28
+ //#endregion
29
+ //#region src/query-all.ts
30
+ /**
31
+ * Find all descendant elements matching the predicate.
32
+ *
33
+ * @param instance - Root TestInstance to search from.
34
+ * @param predicate - Function that returns true for matching elements.
35
+ * @param options - Optional query configuration.
36
+ * @returns Array of matching elements in tree order.
37
+ */
38
+ function queryAll(instance, predicate, options) {
39
+ const includeSelf = options?.includeSelf ?? false;
40
+ const matchDeepestOnly = options?.matchDeepestOnly ?? false;
41
+ const results = [];
42
+ const matchingDescendants = [];
43
+ instance.children.forEach((child) => {
44
+ if (typeof child === "string") return;
45
+ matchingDescendants.push(...queryAll(child, predicate, {
46
+ ...options,
47
+ includeSelf: true
48
+ }));
49
+ });
50
+ if (includeSelf && (matchingDescendants.length === 0 || !matchDeepestOnly) && predicate(instance)) results.push(instance);
51
+ results.push(...matchingDescendants);
52
+ return results;
91
53
  }
92
- function renderChildrenToJson(children) {
93
- const result = [];
94
- for (const child of children) {
95
- if (child.tag === Tag.Instance) {
96
- const renderedChild = renderInstanceToJson(child);
97
- if (renderedChild != null) {
98
- result.push(renderedChild);
99
- }
100
- } else {
101
- const renderedChild = renderTextInstanceToJson(child);
102
- if (renderedChild != null) {
103
- result.push(renderedChild);
104
- }
105
- }
106
- }
107
- return result;
54
+ //#endregion
55
+ //#region src/to-json.ts
56
+ function containerToJson(container) {
57
+ return {
58
+ type: "",
59
+ props: {},
60
+ children: childrenToJson(container.children),
61
+ $$typeof: Symbol.for("react.test.json")
62
+ };
108
63
  }
109
-
110
- // src/host-element.ts
111
- var instanceMap = /* @__PURE__ */ new WeakMap();
112
- var HostElement = class _HostElement {
113
- constructor(instance) {
114
- this.instance = instance;
115
- }
116
- /** The element type (e.g., "div", "span"). Empty string for container. */
117
- get type() {
118
- return this.instance.tag === Tag.Instance ? this.instance.type : CONTAINER_TYPE;
119
- }
120
- /** The element's props object. */
121
- get props() {
122
- return this.instance.tag === Tag.Instance ? this.instance.props : {};
123
- }
124
- /** The parent element, or null if this is the root container. */
125
- get parent() {
126
- const parentInstance = this.instance.parent;
127
- if (parentInstance == null) {
128
- return null;
129
- }
130
- return _HostElement.fromInstance(parentInstance);
131
- }
132
- /** Array of child nodes (elements and text strings). Hidden children are excluded. */
133
- get children() {
134
- const result = this.instance.children.filter((child) => !child.isHidden).map((child) => getHostNodeForInstance(child));
135
- return result;
136
- }
137
- /**
138
- * Access to the underlying React Fiber node. This is an unstable API that exposes
139
- * internal react-reconciler structures which may change without warning in future
140
- * React versions. Use with caution and only when absolutely necessary.
141
- *
142
- * @returns The Fiber node for this instance, or null if this is a container.
143
- */
144
- get unstable_fiber() {
145
- return this.instance.tag === Tag.Instance ? this.instance.unstable_fiber : null;
146
- }
147
- /**
148
- * Convert this element to a JSON representation suitable for snapshots.
149
- *
150
- * @returns JSON element or null if the element is hidden.
151
- */
152
- toJSON() {
153
- return this.instance.tag === Tag.Container ? renderContainerToJson(this.instance) : renderInstanceToJson(this.instance);
154
- }
155
- /**
156
- * Find all descendant elements matching the predicate.
157
- *
158
- * @param predicate - Function that returns true for matching elements.
159
- * @param options - Optional query configuration.
160
- * @returns Array of matching elements.
161
- */
162
- queryAll(predicate, options) {
163
- return queryAll(this, predicate, options);
164
- }
165
- /** @internal */
166
- static fromInstance(instance) {
167
- const hostElement = instanceMap.get(instance);
168
- if (hostElement) {
169
- return hostElement;
170
- }
171
- const result = new _HostElement(instance);
172
- instanceMap.set(instance, result);
173
- return result;
174
- }
64
+ function instanceToJson(instance) {
65
+ const shouldExcludeHidden = instance.rootContainer.config.transformHiddenInstanceProps == null;
66
+ if (instance.isHidden && shouldExcludeHidden) return null;
67
+ const { children: _children, ...restProps } = instance.props;
68
+ return {
69
+ type: instance.type,
70
+ props: restProps,
71
+ children: childrenToJson(instance.children),
72
+ $$typeof: Symbol.for("react.test.json")
73
+ };
74
+ }
75
+ function textInstanceToJson(instance) {
76
+ const shouldExcludeHidden = instance.rootContainer.config.transformHiddenInstanceProps == null;
77
+ if (instance.isHidden && shouldExcludeHidden) return null;
78
+ return instance.text;
79
+ }
80
+ function childrenToJson(children) {
81
+ const result = [];
82
+ for (const child of children) if (child.tag === Tag.Instance) {
83
+ const renderedChild = instanceToJson(child);
84
+ if (renderedChild != null) result.push(renderedChild);
85
+ } else {
86
+ const renderedChild = textInstanceToJson(child);
87
+ if (renderedChild != null) result.push(renderedChild);
88
+ }
89
+ return result;
90
+ }
91
+ //#endregion
92
+ //#region src/test-instance.ts
93
+ const instanceMap = /* @__PURE__ */ new WeakMap();
94
+ /**
95
+ * Represents a rendered host element in the test renderer tree.
96
+ * Provides a DOM-like API for querying and inspecting rendered components.
97
+ */
98
+ var TestInstance = class TestInstance {
99
+ constructor(instance) {
100
+ this.instance = instance;
101
+ }
102
+ /** The element type (e.g., "div", "span"). Empty string for container. */
103
+ get type() {
104
+ return this.instance.tag === Tag.Instance ? this.instance.type : "";
105
+ }
106
+ /** The element's props object. */
107
+ get props() {
108
+ return this.instance.tag === Tag.Instance ? this.instance.props : {};
109
+ }
110
+ /** The parent element, or null if this is the root container. */
111
+ get parent() {
112
+ const parentInstance = this.instance.parent;
113
+ if (parentInstance == null) return null;
114
+ return TestInstance.fromInstance(parentInstance);
115
+ }
116
+ /** Array of child nodes (elements and text strings). Hidden children are excluded by default. */
117
+ get children() {
118
+ const shouldExcludeHiddenChildren = (this.instance.tag === Tag.Container ? this.instance : this.instance.rootContainer).config.transformHiddenInstanceProps == null;
119
+ return this.instance.children.filter((child) => !child.isHidden || !shouldExcludeHiddenChildren).map((child) => getTestNodeForInstance(child));
120
+ }
121
+ /**
122
+ * Access to the underlying React Fiber node. This is an unstable API that exposes
123
+ * internal react-reconciler structures which may change without warning in future
124
+ * React versions. Use with caution and only when absolutely necessary.
125
+ *
126
+ * @returns The Fiber node for this instance, or null if this is a container.
127
+ */
128
+ get unstable_fiber() {
129
+ return this.instance.tag === Tag.Instance ? this.instance.unstable_fiber : null;
130
+ }
131
+ /**
132
+ * Convert this element to a JSON representation suitable for snapshots.
133
+ *
134
+ * @returns JSON element or null if the element is hidden and hidden nodes are excluded.
135
+ */
136
+ toJSON() {
137
+ return this.instance.tag === Tag.Container ? containerToJson(this.instance) : instanceToJson(this.instance);
138
+ }
139
+ /**
140
+ * Find all descendant elements matching the predicate.
141
+ *
142
+ * @param predicate - Function that returns true for matching elements.
143
+ * @param options - Optional query configuration.
144
+ * @returns Array of matching elements.
145
+ */
146
+ queryAll(predicate, options) {
147
+ return queryAll(this, predicate, options);
148
+ }
149
+ /** @internal */
150
+ static fromInstance(instance) {
151
+ const testInstance = instanceMap.get(instance);
152
+ if (testInstance) return testInstance;
153
+ const result = new TestInstance(instance);
154
+ instanceMap.set(instance, result);
155
+ return result;
156
+ }
175
157
  };
176
- function getHostNodeForInstance(instance) {
177
- switch (instance.tag) {
178
- case Tag.Text:
179
- return instance.text;
180
- case Tag.Instance:
181
- return HostElement.fromInstance(instance);
182
- }
158
+ function getTestNodeForInstance(instance) {
159
+ switch (instance.tag) {
160
+ case Tag.Text: return instance.text;
161
+ case Tag.Instance: return TestInstance.fromInstance(instance);
162
+ }
183
163
  }
184
-
185
- // src/reconciler.ts
186
- import ReactReconciler from "react-reconciler";
187
- import { DefaultEventPriority, NoEventPriority } from "react-reconciler/constants";
188
-
189
- // src/utils.ts
164
+ //#endregion
165
+ //#region src/utils.ts
190
166
  function formatComponentList(names) {
191
- if (names.length === 0) {
192
- return "";
193
- }
194
- if (names.length === 1) {
195
- return `<${names[0]}>`;
196
- }
197
- if (names.length === 2) {
198
- return `<${names[0]}> or <${names[1]}>`;
199
- }
200
- const allButLast = names.slice(0, -1);
201
- const last = names[names.length - 1];
202
- return `${allButLast.map((name) => `<${name}>`).join(", ")}, or <${last}>`;
167
+ if (names.length === 0) return "";
168
+ if (names.length === 1) return `<${names[0]}>`;
169
+ if (names.length === 2) return `<${names[0]}> or <${names[1]}>`;
170
+ const allButLast = names.slice(0, -1);
171
+ const last = names[names.length - 1];
172
+ return `${allButLast.map((name) => `<${name}>`).join(", ")}, or <${last}>`;
203
173
  }
204
-
205
- // src/reconciler.ts
206
- var nodeToInstanceMap = /* @__PURE__ */ new WeakMap();
207
- var currentUpdatePriority = NoEventPriority;
208
- var hostConfig = {
209
- /**
210
- * The reconciler has two modes: mutation mode and persistent mode. You must specify one of them.
211
- *
212
- * If your target platform is similar to the DOM and has methods similar to `appendChild`, `removeChild`,
213
- * and so on, you'll want to use the **mutation mode**. This is the same mode used by React DOM, React ART,
214
- * and the classic React Native renderer.
215
- *
216
- * ```js
217
- * const HostConfig = {
218
- * // ...
219
- * supportsMutation: true,
220
- * // ...
221
- * }
222
- * ```
223
- *
224
- * Depending on the mode, the reconciler will call different methods on your host config.
225
- * If you're not sure which one you want, you likely need the mutation mode.
226
- */
227
- supportsMutation: true,
228
- /**
229
- * The reconciler has two modes: mutation mode and persistent mode. You must specify one of them.
230
- *
231
- * If your target platform has immutable trees, you'll want the **persistent mode** instead. In that mode,
232
- * existing nodes are never mutated, and instead every change clones the parent tree and then replaces
233
- * the whole parent tree at the root. This is the node used by the new React Native renderer, codenamed "Fabric".
234
- *
235
- * ```js
236
- * const HostConfig = {
237
- * // ...
238
- * supportsPersistence: true,
239
- * // ...
240
- * }
241
- * ```
242
- *
243
- * Depending on the mode, the reconciler will call different methods on your host config.
244
- * If you're not sure which one you want, you likely need the mutation mode.
245
- */
246
- supportsPersistence: false,
247
- /**
248
- * #### `createInstance(type, props, rootContainer, hostContext, internalHandle)`
249
- *
250
- * This method should return a newly created node. For example, the DOM renderer would call
251
- * `document.createElement(type)` here and then set the properties from `props`.
252
- *
253
- * You can use `rootContainer` to access the root container associated with that tree. For example,
254
- * in the DOM renderer, this is useful to get the correct `document` reference that the root belongs to.
255
- *
256
- * The `hostContext` parameter lets you keep track of some information about your current place in
257
- * the tree. To learn more about it, see `getChildHostContext` below.
258
- *
259
- * The `internalHandle` data structure is meant to be opaque. If you bend the rules and rely on its
260
- * internal fields, be aware that it may change significantly between versions. You're taking on additional
261
- * maintenance risk by reading from it, and giving up all guarantees if you write something to it.
262
- *
263
- * This method happens **in the render phase**. It can (and usually should) mutate the node it has
264
- * just created before returning it, but it must not modify any other nodes. It must not register
265
- * any event handlers on the parent tree. This is because an instance being created doesn't guarantee
266
- * it would be placed in the tree — it could be left unused and later collected by GC. If you need to do
267
- * something when an instance is definitely in the tree, look at `commitMount` instead.
268
- */
269
- createInstance(type, props, rootContainer, _hostContext, internalHandle) {
270
- return {
271
- tag: Tag.Instance,
272
- type,
273
- props,
274
- isHidden: false,
275
- children: [],
276
- parent: null,
277
- rootContainer,
278
- unstable_fiber: internalHandle
279
- };
280
- },
281
- /**
282
- * #### `createTextInstance(text, rootContainer, hostContext, internalHandle)`
283
- *
284
- * Same as `createInstance`, but for text nodes. If your renderer doesn't support text nodes, you can
285
- * throw here.
286
- */
287
- createTextInstance(text, rootContainer, hostContext, _internalHandle) {
288
- var _a;
289
- if (rootContainer.config.textComponentTypes && !hostContext.isInsideText) {
290
- const componentTypes = (_a = rootContainer.config.publicTextComponentTypes) != null ? _a : rootContainer.config.textComponentTypes;
291
- throw new Error(
292
- `Invariant Violation: Text strings must be rendered within a ${formatComponentList(
293
- componentTypes
294
- )} component. Detected attempt to render "${text}" string within a <${hostContext.type}> component.`
295
- );
296
- }
297
- return {
298
- tag: Tag.Text,
299
- text,
300
- parent: null,
301
- isHidden: false
302
- };
303
- },
304
- /**
305
- * #### `appendInitialChild(parentInstance, child)`
306
- *
307
- * This method should mutate the `parentInstance` and add the child to its list of children.
308
- * For example, in the DOM this would translate to a `parentInstance.appendChild(child)` call.
309
- *
310
- * This method happens **in the render phase**. It can mutate `parentInstance` and `child`, but it
311
- * must not modify any other nodes. It's called while the tree is still being built up and not connected
312
- * to the actual tree on the screen.
313
- */
314
- appendInitialChild: appendChild,
315
- /**
316
- * #### `finalizeInitialChildren(instance, type, props, rootContainer, hostContext)`
317
- *
318
- * In this method, you can perform some final mutations on the `instance`. Unlike with `createInstance`,
319
- * by the time `finalizeInitialChildren` is called, all the initial children have already been added to
320
- * the `instance`, but the instance itself has not yet been connected to the tree on the screen.
321
- *
322
- * This method happens **in the render phase**. It can mutate `instance`, but it must not modify any other
323
- * nodes. It's called while the tree is still being built up and not connected to the actual tree on the screen.
324
- *
325
- * There is a second purpose to this method. It lets you specify whether there is some work that needs to
326
- * happen when the node is connected to the tree on the screen. If you return `true`, the instance will
327
- * receive a `commitMount` call later. See its documentation below.
328
- *
329
- * If you don't want to do anything here, you should return `false`.
330
- */
331
- finalizeInitialChildren(_instance, _type, _props, _rootContainer, _hostContext) {
332
- return false;
333
- },
334
- /**
335
- * #### `shouldSetTextContent(type, props)`
336
- *
337
- * Some target platforms support setting an instance's text content without manually creating a text node.
338
- * For example, in the DOM, you can set `node.textContent` instead of creating a text node and appending it.
339
- *
340
- * If you return `true` from this method, React will assume that this node's children are text, and will
341
- * not create nodes for them. It will instead rely on you to have filled that text during `createInstance`.
342
- * This is a performance optimization. For example, the DOM renderer returns `true` only if `type` is a
343
- * known text-only parent (like `'textarea'`) or if `props.children` has a `'string'` type. If you return `true`,
344
- * you will need to implement `resetTextContent` too.
345
- *
346
- * If you don't want to do anything here, you should return `false`.
347
- * This method happens **in the render phase**. Do not mutate the tree from it.
348
- */
349
- shouldSetTextContent(_type, _props) {
350
- return false;
351
- },
352
- setCurrentUpdatePriority(newPriority) {
353
- currentUpdatePriority = newPriority;
354
- },
355
- getCurrentUpdatePriority() {
356
- return currentUpdatePriority;
357
- },
358
- resolveUpdatePriority() {
359
- return currentUpdatePriority || DefaultEventPriority;
360
- },
361
- shouldAttemptEagerTransition() {
362
- return false;
363
- },
364
- /**
365
- * #### `getRootHostContext(rootContainer)`
366
- *
367
- * This method lets you return the initial host context from the root of the tree. See `getChildHostContext`
368
- * for the explanation of host context.
369
- *
370
- * If you don't intend to use host context, you can return `null`.
371
- * This method happens **in the render phase**. Do not mutate the tree from it.
372
- */
373
- getRootHostContext(rootContainer) {
374
- return {
375
- type: "ROOT",
376
- config: rootContainer.config,
377
- isInsideText: false
378
- };
379
- },
380
- /**
381
- * #### `getChildHostContext(parentHostContext, type, rootContainer)`
382
- *
383
- * Host context lets you track some information about where you are in the tree so that it's available
384
- * inside `createInstance` as the `hostContext` parameter. For example, the DOM renderer uses it to track
385
- * whether it's inside an HTML or an SVG tree, because `createInstance` implementation needs to be
386
- * different for them.
387
- *
388
- * If the node of this `type` does not influence the context you want to pass down, you can return
389
- * `parentHostContext`. Alternatively, you can return any custom object representing the information
390
- * you want to pass down.
391
- *
392
- * If you don't want to do anything here, return `parentHostContext`.
393
- *
394
- * This method happens **in the render phase**. Do not mutate the tree from it.
395
- */
396
- getChildHostContext(parentHostContext, type) {
397
- var _a;
398
- const isInsideText = Boolean((_a = parentHostContext.config.textComponentTypes) == null ? void 0 : _a.includes(type));
399
- return __spreadProps(__spreadValues({}, parentHostContext), { type, isInsideText });
400
- },
401
- /**
402
- * #### `getPublicInstance(instance)`
403
- *
404
- * Determines what object gets exposed as a ref. You'll likely want to return the `instance` itself. But
405
- * in some cases it might make sense to only expose some part of it.
406
- *
407
- * If you don't want to do anything here, return `instance`.
408
- */
409
- getPublicInstance(instance) {
410
- switch (instance.tag) {
411
- case Tag.Instance: {
412
- const createNodeMock = instance.rootContainer.config.createNodeMock;
413
- const mockNode = createNodeMock({
414
- type: instance.type,
415
- props: instance.props,
416
- key: null
417
- });
418
- nodeToInstanceMap.set(mockNode, instance);
419
- return mockNode;
420
- }
421
- default:
422
- return instance;
423
- }
424
- },
425
- /**
426
- * #### `prepareForCommit(containerInfo)`
427
- *
428
- * This method lets you store some information before React starts making changes to the tree on
429
- * the screen. For example, the DOM renderer stores the current text selection so that it can later
430
- * restore it. This method is mirrored by `resetAfterCommit`.
431
- *
432
- * Even if you don't want to do anything here, you need to return `null` from it.
433
- */
434
- prepareForCommit(_containerInfo) {
435
- return null;
436
- },
437
- /**
438
- * #### `resetAfterCommit(containerInfo)`
439
- *
440
- * This method is called right after React has performed the tree mutations. You can use it to restore
441
- * something you've stored in `prepareForCommit` — for example, text selection.
442
- *
443
- * You can leave it empty.
444
- */
445
- resetAfterCommit(_containerInfo) {
446
- },
447
- /**
448
- * #### `preparePortalMount(containerInfo)`
449
- *
450
- * This method is called for a container that's used as a portal target. Usually you can leave it empty.
451
- */
452
- preparePortalMount(_containerInfo) {
453
- },
454
- /**
455
- * #### `scheduleTimeout(fn, delay)`
456
- *
457
- * You can proxy this to `setTimeout` or its equivalent in your environment.
458
- */
459
- scheduleTimeout: setTimeout,
460
- /**
461
- * #### `cancelTimeout(id)`
462
- *
463
- * You can proxy this to `clearTimeout` or its equivalent in your environment.
464
- */
465
- cancelTimeout: clearTimeout,
466
- /**
467
- * #### `noTimeout`
468
- *
469
- * This is a property (not a function) that should be set to something that can never be a valid timeout ID.
470
- * For example, you can set it to `-1`.
471
- */
472
- noTimeout: -1,
473
- /**
474
- * #### `supportsMicrotasks`
475
- *
476
- * Set this to `true` to indicate that your renderer supports `scheduleMicrotask`. We use microtasks as part
477
- * of our discrete event implementation in React DOM. If you're not sure if your renderer should support this,
478
- * you probably should. The option to not implement `scheduleMicrotask` exists so that platforms with more control
479
- * over user events, like React Native, can choose to use a different mechanism.
480
- */
481
- supportsMicrotasks: true,
482
- /**
483
- * #### `scheduleMicrotask(fn)`
484
- *
485
- * Optional. You can proxy this to `queueMicrotask` or its equivalent in your environment.
486
- */
487
- scheduleMicrotask: queueMicrotask,
488
- /**
489
- * #### `isPrimaryRenderer`
490
- *
491
- * This is a property (not a function) that should be set to `true` if your renderer is the main one on the
492
- * page. For example, if you're writing a renderer for the Terminal, it makes sense to set it to `true`, but
493
- * if your renderer is used *on top of* React DOM or some other existing renderer, set it to `false`.
494
- */
495
- isPrimaryRenderer: true,
496
- /**
497
- * Whether the renderer shouldn't trigger missing `act()` warnings
498
- */
499
- warnsIfNotActing: true,
500
- getInstanceFromNode(node) {
501
- const instance = nodeToInstanceMap.get(node);
502
- if (instance !== void 0) {
503
- return instance.unstable_fiber;
504
- }
505
- return null;
506
- },
507
- beforeActiveInstanceBlur() {
508
- },
509
- afterActiveInstanceBlur() {
510
- },
511
- prepareScopeUpdate(scopeInstance, instance) {
512
- nodeToInstanceMap.set(scopeInstance, instance);
513
- },
514
- getInstanceFromScope(scopeInstance) {
515
- var _a;
516
- return (_a = nodeToInstanceMap.get(scopeInstance)) != null ? _a : null;
517
- },
518
- detachDeletedInstance(_node) {
519
- },
520
- /**
521
- * #### `appendChild(parentInstance, child)`
522
- *
523
- * This method should mutate the `parentInstance` and add the child to its list of children. For example,
524
- * in the DOM this would translate to a `parentInstance.appendChild(child)` call.
525
- *
526
- * Although this method currently runs in the commit phase, you still should not mutate any other nodes
527
- * in it. If you need to do some additional work when a node is definitely connected to the visible tree, look at `commitMount`.
528
- */
529
- appendChild,
530
- /**
531
- * #### `appendChildToContainer(container, child)`
532
- *
533
- * Same as `appendChild`, but for when a node is attached to the root container. This is useful if attaching
534
- * to the root has a slightly different implementation, or if the root container nodes are of a different
535
- * type than the rest of the tree.
536
- */
537
- appendChildToContainer: appendChild,
538
- /**
539
- * #### `insertBefore(parentInstance, child, beforeChild)`
540
- *
541
- * This method should mutate the `parentInstance` and place the `child` before `beforeChild` in the list of
542
- * its children. For example, in the DOM this would translate to a `parentInstance.insertBefore(child, beforeChild)` call.
543
- *
544
- * Note that React uses this method both for insertions and for reordering nodes. Similar to DOM, it is expected
545
- * that you can call `insertBefore` to reposition an existing child. Do not mutate any other parts of the tree from it.
546
- */
547
- insertBefore,
548
- /**
549
- * #### `insertInContainerBefore(container, child, beforeChild)
550
- *
551
- * Same as `insertBefore`, but for when a node is attached to the root container. This is useful if attaching
552
- * to the root has a slightly different implementation, or if the root container nodes are of a different type
553
- * than the rest of the tree.
554
- */
555
- insertInContainerBefore: insertBefore,
556
- /**
557
- * #### `removeChild(parentInstance, child)`
558
- *
559
- * This method should mutate the `parentInstance` to remove the `child` from the list of its children.
560
- *
561
- * React will only call it for the top-level node that is being removed. It is expected that garbage collection
562
- * would take care of the whole subtree. You are not expected to traverse the child tree in it.
563
- */
564
- removeChild,
565
- /**
566
- * #### `removeChildFromContainer(container, child)`
567
- *
568
- * Same as `removeChild`, but for when a node is detached from the root container. This is useful if attaching
569
- * to the root has a slightly different implementation, or if the root container nodes are of a different type
570
- * than the rest of the tree.
571
- */
572
- removeChildFromContainer: removeChild,
573
- /**
574
- * #### `resetTextContent(instance)`
575
- *
576
- * If you returned `true` from `shouldSetTextContent` for the previous props, but returned `false` from
577
- * `shouldSetTextContent` for the next props, React will call this method so that you can clear the text
578
- * content you were managing manually. For example, in the DOM you could set `node.textContent = ''`.
579
- *
580
- * If you never return `true` from `shouldSetTextContent`, you can leave it empty.
581
- */
582
- resetTextContent(_instance) {
583
- },
584
- /**
585
- * #### `commitTextUpdate(textInstance, prevText, nextText)`
586
- *
587
- * This method should mutate the `textInstance` and update its text content to `nextText`.
588
- *
589
- * Here, `textInstance` is a node created by `createTextInstance`.
590
- */
591
- commitTextUpdate(textInstance, _oldText, newText) {
592
- textInstance.text = newText;
593
- },
594
- /**
595
- * #### `commitMount(instance, type, props, internalHandle)`
596
- *
597
- * This method is only called if you returned `true` from `finalizeInitialChildren` for this instance.
598
- *
599
- * It lets you do some additional work after the node is actually attached to the tree on the screen for
600
- * the first time. For example, the DOM renderer uses it to trigger focus on nodes with the `autoFocus` attribute.
601
- *
602
- * Note that `commitMount` does not mirror `removeChild` one to one because `removeChild` is only called for
603
- * the top-level removed node. This is why ideally `commitMount` should not mutate any nodes other than the
604
- * `instance` itself. For example, if it registers some events on some node above, it will be your responsibility
605
- * to traverse the tree in `removeChild` and clean them up, which is not ideal.
606
- *
607
- * The `internalHandle` data structure is meant to be opaque. If you bend the rules and rely on its internal
608
- * fields, be aware that it may change significantly between versions. You're taking on additional maintenance
609
- * risk by reading from it, and giving up all guarantees if you write something to it.
610
- *
611
- * If you never return `true` from `finalizeInitialChildren`, you can leave it empty.
612
- */
613
- commitMount(_instance, _type, _props, _internalHandle) {
614
- },
615
- /**
616
- * #### `commitUpdate(instance, type, prevProps, nextProps, internalHandle)`
617
- *
618
- * This method should mutate the `instance` according to the set of changes in `updatePayload`. Here, `updatePayload`
619
- * is the object that you've returned from `prepareUpdate` and has an arbitrary structure that makes sense for your
620
- * renderer. For example, the DOM renderer returns an update payload like `[prop1, value1, prop2, value2, ...]` from
621
- * `prepareUpdate`, and that structure gets passed into `commitUpdate`. Ideally, all the diffing and calculation
622
- * should happen inside `prepareUpdate` so that `commitUpdate` can be fast and straightforward.
623
- *
624
- * The `internalHandle` data structure is meant to be opaque. If you bend the rules and rely on its internal fields,
625
- * be aware that it may change significantly between versions. You're taking on additional maintenance risk by
626
- * reading from it, and giving up all guarantees if you write something to it.
627
- */
628
- // @ts-expect-error @types/react-reconciler types don't fully match react-reconciler's actual Flow types.
629
- // Correctness is verified through tests.
630
- commitUpdate(instance, type, _prevProps, nextProps, internalHandle) {
631
- instance.type = type;
632
- instance.props = nextProps;
633
- instance.unstable_fiber = internalHandle;
634
- },
635
- /**
636
- * #### `hideInstance(instance)`
637
- *
638
- * This method should make the `instance` invisible without removing it from the tree. For example, it can apply
639
- * visual styling to hide it. It is used by Suspense to hide the tree while the fallback is visible.
640
- */
641
- hideInstance(instance) {
642
- instance.isHidden = true;
643
- },
644
- /**
645
- * #### `hideTextInstance(textInstance)`
646
- *
647
- * Same as `hideInstance`, but for nodes created by `createTextInstance`.
648
- */
649
- hideTextInstance(textInstance) {
650
- textInstance.isHidden = true;
651
- },
652
- /**
653
- * #### `unhideInstance(instance, props)`
654
- *
655
- * This method should make the `instance` visible, undoing what `hideInstance` did.
656
- */
657
- unhideInstance(instance, _props) {
658
- instance.isHidden = false;
659
- },
660
- /**
661
- * #### `unhideTextInstance(textInstance, text)`
662
- *
663
- * Same as `unhideInstance`, but for nodes created by `createTextInstance`.
664
- */
665
- unhideTextInstance(textInstance, _text) {
666
- textInstance.isHidden = false;
667
- },
668
- /**
669
- * #### `clearContainer(container)`
670
- *
671
- * This method should mutate the `container` root node and remove all children from it.
672
- */
673
- clearContainer(container) {
674
- container.children.forEach((child) => {
675
- child.parent = null;
676
- });
677
- container.children.splice(0);
678
- },
679
- /**
680
- * #### `maySuspendCommit(type, props)`
681
- *
682
- * This method is called during render to determine if the Host Component type and props require
683
- * some kind of loading process to complete before committing an update.
684
- */
685
- maySuspendCommit(_type, _props) {
686
- return false;
687
- },
688
- /**
689
- * #### `preloadInstance(type, props)`
690
- *
691
- * This method may be called during render if the Host Component type and props might suspend a commit.
692
- * It can be used to initiate any work that might shorten the duration of a suspended commit.
693
- */
694
- preloadInstance(_type, _props) {
695
- return true;
696
- },
697
- /**
698
- * #### `startSuspendingCommit()`
699
- *
700
- * This method is called just before the commit phase. Use it to set up any necessary state while any Host
701
- * Components that might suspend this commit are evaluated to determine if the commit must be suspended.
702
- */
703
- startSuspendingCommit() {
704
- },
705
- /**
706
- * #### `suspendInstance(type, props)`
707
- *
708
- * This method is called after `startSuspendingCommit` for each Host Component that indicated it might
709
- * suspend a commit.
710
- */
711
- suspendInstance() {
712
- },
713
- /**
714
- * #### `waitForCommitToBeReady()`
715
- *
716
- * This method is called after all `suspendInstance` calls are complete.
717
- *
718
- * Return `null` if the commit can happen immediately.
719
- * Return `(initiateCommit: Function) => Function` if the commit must be suspended. The argument to this
720
- * callback will initiate the commit when called. The return value is a cancellation function that the
721
- * Reconciler can use to abort the commit.
722
- */
723
- waitForCommitToBeReady() {
724
- return null;
725
- },
726
- // -------------------
727
- // Hydration Methods
728
- // (optional)
729
- // You can optionally implement hydration to "attach" to the existing tree during the initial render instead
730
- // of creating it from scratch. For example, the DOM renderer uses this to attach to an HTML markup.
731
- //
732
- // To support hydration, you need to declare `supportsHydration: true` and then implement the methods in
733
- // the "Hydration" section [listed in this file](https://github.com/facebook/react/blob/master/packages/react-reconciler/src/forks/ReactFiberHostConfig.custom.js).
734
- // File an issue if you need help.
735
- // -------------------
736
- supportsHydration: false,
737
- NotPendingTransition: null,
738
- resetFormInstance(_form) {
739
- },
740
- requestPostPaintCallback(_callback) {
741
- }
742
- };
743
- var TestReconciler = ReactReconciler(hostConfig);
174
+ //#endregion
175
+ //#region src/reconciler.ts
176
+ const nodeToInstanceMap = /* @__PURE__ */ new WeakMap();
177
+ let currentUpdatePriority = NoEventPriority;
178
+ const TestReconciler = ReactReconciler({
179
+ supportsMutation: true,
180
+ supportsPersistence: false,
181
+ createInstance(type, props, rootContainer, _hostContext, internalHandle) {
182
+ mark("reconciler/createInstance", { type });
183
+ return {
184
+ tag: Tag.Instance,
185
+ type,
186
+ props,
187
+ propsBeforeHiding: null,
188
+ isHidden: false,
189
+ children: [],
190
+ parent: null,
191
+ rootContainer,
192
+ unstable_fiber: internalHandle
193
+ };
194
+ },
195
+ createTextInstance(text, rootContainer, hostContext, _internalHandle) {
196
+ mark("reconciler/createTextInstance", { text });
197
+ if (rootContainer.config.textComponentTypes && !hostContext.isInsideText) {
198
+ const componentTypes = rootContainer.config.publicTextComponentTypes ?? rootContainer.config.textComponentTypes;
199
+ throw new Error(`Invariant Violation: Text strings must be rendered within a ${formatComponentList(componentTypes)} component. Detected attempt to render "${text}" string within a <${hostContext.type}> component.`);
200
+ }
201
+ return {
202
+ tag: Tag.Text,
203
+ text,
204
+ parent: null,
205
+ rootContainer,
206
+ isHidden: false
207
+ };
208
+ },
209
+ appendInitialChild(parentInstance, child) {
210
+ if (globalThis.TEST_RENDERER_ENABLE_PROFILING) mark("reconciler/appendInitialChild", {
211
+ parentType: parentInstance.type,
212
+ childType: formatInstanceType(child)
213
+ });
214
+ appendChild(parentInstance, child);
215
+ },
216
+ finalizeInitialChildren(instance, _type, _props, _rootContainer, _hostContext) {
217
+ mark("reconciler/finalizeInitialChildren", { type: instance.type });
218
+ return false;
219
+ },
220
+ shouldSetTextContent(type, _props) {
221
+ mark("reconciler/shouldSetTextContent", {
222
+ type,
223
+ result: false
224
+ });
225
+ return false;
226
+ },
227
+ setCurrentUpdatePriority(priority) {
228
+ mark("reconciler/setCurrentUpdatePriority", { priority });
229
+ currentUpdatePriority = priority;
230
+ },
231
+ getCurrentUpdatePriority() {
232
+ return currentUpdatePriority;
233
+ },
234
+ resolveUpdatePriority() {
235
+ const priority = currentUpdatePriority || DefaultEventPriority;
236
+ mark("reconciler/resolveUpdatePriority", { priority });
237
+ return priority;
238
+ },
239
+ trackSchedulerEvent() {
240
+ mark("reconciler/trackSchedulerEvent");
241
+ },
242
+ resolveEventType() {
243
+ mark("reconciler/resolveEventType");
244
+ return null;
245
+ },
246
+ resolveEventTimeStamp() {
247
+ const timestamp = -1.1;
248
+ mark("reconciler/resolveEventTimeStamp", { timestamp });
249
+ return timestamp;
250
+ },
251
+ shouldAttemptEagerTransition() {
252
+ mark("reconciler/shouldAttemptEagerTransition", { result: false });
253
+ return false;
254
+ },
255
+ getRootHostContext(rootContainer) {
256
+ mark("reconciler/getRootHostContext");
257
+ return {
258
+ type: "ROOT",
259
+ config: rootContainer.config,
260
+ isInsideText: false
261
+ };
262
+ },
263
+ getChildHostContext(parentHostContext, type) {
264
+ mark("reconciler/getChildHostContext", { type });
265
+ const isInsideText = Boolean(parentHostContext.config.textComponentTypes?.includes(type));
266
+ return {
267
+ ...parentHostContext,
268
+ type,
269
+ isInsideText
270
+ };
271
+ },
272
+ getPublicInstance(instance) {
273
+ if (globalThis.TEST_RENDERER_ENABLE_PROFILING) mark("reconciler/getPublicInstance", { type: formatInstanceType(instance) });
274
+ switch (instance.tag) {
275
+ case Tag.Instance: {
276
+ const testInstance = TestInstance.fromInstance(instance);
277
+ nodeToInstanceMap.set(testInstance, instance);
278
+ return testInstance;
279
+ }
280
+ default: return null;
281
+ }
282
+ },
283
+ prepareForCommit(_containerInfo) {
284
+ mark("reconciler/prepareForCommit");
285
+ measureStart("react/commit");
286
+ return null;
287
+ },
288
+ resetAfterCommit(_containerInfo) {
289
+ measureEnd("react/commit");
290
+ mark("reconciler/resetAfterCommit");
291
+ },
292
+ preparePortalMount(_containerInfo) {
293
+ mark("reconciler/preparePortalMount");
294
+ },
295
+ scheduleTimeout(fn, delay) {
296
+ const id = setTimeout(() => {
297
+ mark("reconciler/scheduled timeout:start");
298
+ fn();
299
+ mark("reconciler/scheduled timeout:end");
300
+ }, delay);
301
+ mark("reconciler/scheduleTimeout", { id });
302
+ return id;
303
+ },
304
+ cancelTimeout(id) {
305
+ mark("reconciler/cancelTimeout", { id });
306
+ clearTimeout(id);
307
+ },
308
+ noTimeout: -1,
309
+ supportsMicrotasks: true,
310
+ scheduleMicrotask(fn) {
311
+ mark("reconciler/scheduleMicrotask");
312
+ queueMicrotask(() => {
313
+ mark("reconciler/scheduled microtask:start");
314
+ fn();
315
+ mark("reconciler/scheduled microtask:end");
316
+ });
317
+ },
318
+ isPrimaryRenderer: true,
319
+ warnsIfNotActing: true,
320
+ getInstanceFromNode(node) {
321
+ mark("reconciler/getInstanceFromNode");
322
+ const instance = nodeToInstanceMap.get(node);
323
+ if (instance !== void 0) return instance.unstable_fiber;
324
+ return null;
325
+ },
326
+ beforeActiveInstanceBlur() {
327
+ mark("reconciler/beforeActiveInstanceBlur");
328
+ },
329
+ afterActiveInstanceBlur() {
330
+ mark("reconciler/afterActiveInstanceBlur");
331
+ },
332
+ prepareScopeUpdate(scopeInstance, instance) {
333
+ mark("reconciler/prepareScopeUpdate");
334
+ nodeToInstanceMap.set(scopeInstance, instance);
335
+ },
336
+ getInstanceFromScope(scopeInstance) {
337
+ mark("reconciler/getInstanceFromScope");
338
+ return nodeToInstanceMap.get(scopeInstance) ?? null;
339
+ },
340
+ detachDeletedInstance(_node) {
341
+ mark("reconciler/detachDeletedInstance");
342
+ },
343
+ appendChild(parentInstance, child) {
344
+ if (globalThis.TEST_RENDERER_ENABLE_PROFILING) mark("reconciler/appendChild", {
345
+ parentType: parentInstance.type,
346
+ childType: formatInstanceType(child)
347
+ });
348
+ appendChild(parentInstance, child);
349
+ },
350
+ appendChildToContainer(container, child) {
351
+ if (globalThis.TEST_RENDERER_ENABLE_PROFILING) mark("reconciler/appendChildToContainer", { childType: formatInstanceType(child) });
352
+ appendChild(container, child);
353
+ },
354
+ insertBefore(parentInstance, child, beforeChild) {
355
+ if (globalThis.TEST_RENDERER_ENABLE_PROFILING) mark("reconciler/insertBefore", {
356
+ parentType: parentInstance.type,
357
+ childType: formatInstanceType(child),
358
+ beforeChildType: formatInstanceType(beforeChild)
359
+ });
360
+ insertBefore(parentInstance, child, beforeChild);
361
+ },
362
+ insertInContainerBefore(container, child, beforeChild) {
363
+ if (globalThis.TEST_RENDERER_ENABLE_PROFILING) mark("reconciler/insertInContainerBefore", {
364
+ childType: formatInstanceType(child),
365
+ beforeChildType: formatInstanceType(beforeChild)
366
+ });
367
+ insertBefore(container, child, beforeChild);
368
+ },
369
+ removeChild(parentInstance, child) {
370
+ if (globalThis.TEST_RENDERER_ENABLE_PROFILING) mark("reconciler/removeChild", {
371
+ parentType: parentInstance.type,
372
+ childType: formatInstanceType(child)
373
+ });
374
+ removeChild(parentInstance, child);
375
+ },
376
+ removeChildFromContainer(container, child) {
377
+ if (globalThis.TEST_RENDERER_ENABLE_PROFILING) mark("reconciler/removeChildFromContainer", { childType: formatInstanceType(child) });
378
+ removeChild(container, child);
379
+ },
380
+ resetTextContent(instance) {
381
+ mark("reconciler/resetTextContent", { type: instance.type });
382
+ },
383
+ commitTextUpdate(textInstance, oldText, newText) {
384
+ mark("reconciler/commitTextUpdate", {
385
+ oldText,
386
+ newText
387
+ });
388
+ textInstance.text = newText;
389
+ },
390
+ commitMount(_instance, type, _props, _internalHandle) {
391
+ mark("reconciler/commitMount", { type });
392
+ },
393
+ commitUpdate(instance, type, _prevProps, nextProps, internalHandle) {
394
+ mark("reconciler/commitUpdate", { type });
395
+ instance.type = type;
396
+ if (instance.isHidden && instance.rootContainer.config.transformHiddenInstanceProps != null) {
397
+ instance.propsBeforeHiding = nextProps;
398
+ instance.props = instance.rootContainer.config.transformHiddenInstanceProps({
399
+ props: nextProps,
400
+ type: instance.type
401
+ });
402
+ } else {
403
+ instance.props = nextProps;
404
+ instance.propsBeforeHiding = null;
405
+ }
406
+ instance.unstable_fiber = internalHandle;
407
+ },
408
+ hideInstance(instance) {
409
+ mark("reconciler/hideInstance", { type: instance.type });
410
+ if (instance.isHidden) return;
411
+ instance.isHidden = true;
412
+ instance.propsBeforeHiding = instance.props;
413
+ const transformHiddenInstanceProps = instance.rootContainer.config.transformHiddenInstanceProps;
414
+ if (transformHiddenInstanceProps) {
415
+ const { props, type } = instance;
416
+ instance.props = transformHiddenInstanceProps({
417
+ props,
418
+ type
419
+ });
420
+ }
421
+ },
422
+ hideTextInstance(textInstance) {
423
+ mark("reconciler/hideTextInstance", { text: textInstance.text });
424
+ textInstance.isHidden = true;
425
+ },
426
+ unhideInstance(instance, _props) {
427
+ mark("reconciler/unhideInstance", { type: instance.type });
428
+ instance.isHidden = false;
429
+ if (instance.rootContainer.config.transformHiddenInstanceProps && instance.propsBeforeHiding) {
430
+ instance.props = instance.propsBeforeHiding;
431
+ instance.propsBeforeHiding = null;
432
+ }
433
+ },
434
+ unhideTextInstance(textInstance, _text) {
435
+ mark("reconciler/unhideTextInstance", { text: textInstance.text });
436
+ textInstance.isHidden = false;
437
+ },
438
+ clearContainer(container) {
439
+ mark("reconciler/clearContainer");
440
+ container.children.forEach((child) => {
441
+ child.parent = null;
442
+ });
443
+ container.children.splice(0);
444
+ },
445
+ maySuspendCommit(type, _props) {
446
+ mark("reconciler/maySuspendCommit", { type });
447
+ return false;
448
+ },
449
+ preloadInstance(type, _props) {
450
+ mark("reconciler/preloadInstance", { type });
451
+ return true;
452
+ },
453
+ startSuspendingCommit() {
454
+ mark("reconciler/startSuspendingCommit");
455
+ },
456
+ suspendInstance(type, _props) {
457
+ mark("reconciler/suspendInstance", { type });
458
+ },
459
+ waitForCommitToBeReady(type, _props) {
460
+ mark("reconciler/waitForCommitToBeReady", { type });
461
+ return null;
462
+ },
463
+ supportsHydration: false,
464
+ NotPendingTransition: null,
465
+ resetFormInstance(_form) {
466
+ mark("reconciler/resetFormInstance");
467
+ },
468
+ requestPostPaintCallback(_callback) {
469
+ mark("reconciler/requestPostPaintCallback");
470
+ }
471
+ });
472
+ /**
473
+ * This method should mutate the `parentInstance` and add the child to its list of children. For example,
474
+ * in the DOM this would translate to a `parentInstance.appendChild(child)` call.
475
+ *
476
+ * Although this method currently runs in the commit phase, you still should not mutate any other nodes
477
+ * in it. If you need to do some additional work when a node is definitely connected to the visible tree,
478
+ * look at `commitMount`.
479
+ */
744
480
  function appendChild(parentInstance, child) {
745
- const index = parentInstance.children.indexOf(child);
746
- if (index !== -1) {
747
- parentInstance.children.splice(index, 1);
748
- }
749
- child.parent = parentInstance;
750
- parentInstance.children.push(child);
481
+ const index = parentInstance.children.indexOf(child);
482
+ if (index !== -1) parentInstance.children.splice(index, 1);
483
+ child.parent = parentInstance;
484
+ parentInstance.children.push(child);
751
485
  }
486
+ /**
487
+ * This method should mutate the `parentInstance` and place the `child` before `beforeChild` in the list
488
+ * of its children. For example, in the DOM this would translate to a
489
+ * `parentInstance.insertBefore(child, beforeChild)` call.
490
+ *
491
+ * Note that React uses this method both for insertions and for reordering nodes. Similar to DOM, it is
492
+ * expected that you can call `insertBefore` to reposition an existing child. Do not mutate any other parts
493
+ * of the tree from it.
494
+ */
752
495
  function insertBefore(parentInstance, child, beforeChild) {
753
- const index = parentInstance.children.indexOf(child);
754
- if (index !== -1) {
755
- parentInstance.children.splice(index, 1);
756
- }
757
- child.parent = parentInstance;
758
- const beforeIndex = parentInstance.children.indexOf(beforeChild);
759
- parentInstance.children.splice(beforeIndex, 0, child);
496
+ const index = parentInstance.children.indexOf(child);
497
+ if (index !== -1) parentInstance.children.splice(index, 1);
498
+ child.parent = parentInstance;
499
+ const beforeIndex = parentInstance.children.indexOf(beforeChild);
500
+ parentInstance.children.splice(beforeIndex, 0, child);
760
501
  }
502
+ /**
503
+ * This method should mutate the `parentInstance` to remove the `child` from the list of its children.
504
+ *
505
+ * React will only call it for the top-level node that is being removed. It is expected that garbage
506
+ * collection would take care of the whole subtree. You are not expected to traverse the child tree in it.
507
+ */
761
508
  function removeChild(parentInstance, child) {
762
- const index = parentInstance.children.indexOf(child);
763
- parentInstance.children.splice(index, 1);
764
- child.parent = null;
509
+ const index = parentInstance.children.indexOf(child);
510
+ parentInstance.children.splice(index, 1);
511
+ child.parent = null;
765
512
  }
766
-
767
- // src/renderer.ts
768
- var defaultCreateMockNode = () => ({});
769
- var defaultOnUncaughtError = (error, errorInfo) => {
770
- console.error("Uncaught error:", error, errorInfo);
513
+ function formatInstanceType(instance) {
514
+ return instance.tag === Tag.Text ? `text: "${instance.text}"` : instance.type;
515
+ }
516
+ //#endregion
517
+ //#region src/renderer.ts
518
+ const defaultOnUncaughtError = (error, errorInfo) => {
519
+ console.error("Uncaught error:", error, errorInfo);
771
520
  };
772
- var defaultOnCaughtError = (error, errorInfo) => {
773
- console.error("Caught error:", error, errorInfo);
521
+ const defaultOnCaughtError = (error, errorInfo) => {
522
+ console.error("Caught error:", error, errorInfo);
774
523
  };
775
- var defaultOnRecoverableError = (error, errorInfo) => {
776
- console.error("Recoverable error:", error, errorInfo);
524
+ const defaultOnRecoverableError = (error, errorInfo) => {
525
+ console.error("Recoverable error:", error, errorInfo);
777
526
  };
527
+ /**
528
+ * Create a new test renderer root instance.
529
+ *
530
+ * @param options - Optional configuration for the renderer.
531
+ * @returns A Root instance with render, unmount, and container properties.
532
+ */
778
533
  function createRoot(options) {
779
- var _a, _b, _c, _d, _e, _f;
780
- let container = {
781
- tag: Tag.Container,
782
- parent: null,
783
- children: [],
784
- isHidden: false,
785
- config: {
786
- textComponentTypes: options == null ? void 0 : options.textComponentTypes,
787
- publicTextComponentTypes: options == null ? void 0 : options.publicTextComponentTypes,
788
- createNodeMock: (_a = options == null ? void 0 : options.createNodeMock) != null ? _a : defaultCreateMockNode
789
- }
790
- };
791
- let containerFiber = TestReconciler.createContainer(
792
- container,
793
- ConcurrentRoot,
794
- null,
795
- // hydrationCallbacks
796
- (_b = options == null ? void 0 : options.isStrictMode) != null ? _b : false,
797
- false,
798
- // concurrentUpdatesByDefaultOverride
799
- (_c = options == null ? void 0 : options.identifierPrefix) != null ? _c : "",
800
- (_d = options == null ? void 0 : options.onUncaughtError) != null ? _d : defaultOnUncaughtError,
801
- (_e = options == null ? void 0 : options.onCaughtError) != null ? _e : defaultOnCaughtError,
802
- // @ts-expect-error @types/react-reconciler types don't include onRecoverableError parameter
803
- // in the createContainer signature, but react-reconciler's actual Flow types do.
804
- // Correctness is verified through tests.
805
- (_f = options == null ? void 0 : options.onRecoverableError) != null ? _f : defaultOnRecoverableError,
806
- null
807
- // transitionCallbacks
808
- );
809
- const render = (element) => {
810
- if (containerFiber == null) {
811
- throw new Error("Cannot render after unmount");
812
- }
813
- TestReconciler.updateContainer(element, containerFiber, null, null);
814
- };
815
- const unmount = () => {
816
- if (container == null) {
817
- return;
818
- }
819
- TestReconciler.updateContainer(null, containerFiber, null, null);
820
- containerFiber = null;
821
- container = null;
822
- };
823
- return {
824
- render,
825
- unmount,
826
- get container() {
827
- if (container == null) {
828
- throw new Error("Cannot access .container on unmounted test renderer");
829
- }
830
- return HostElement.fromInstance(container);
831
- }
832
- };
534
+ measureStart("createRoot");
535
+ let container = {
536
+ tag: Tag.Container,
537
+ parent: null,
538
+ children: [],
539
+ isHidden: false,
540
+ config: {
541
+ textComponentTypes: options?.textComponentTypes,
542
+ publicTextComponentTypes: options?.publicTextComponentTypes,
543
+ transformHiddenInstanceProps: options?.transformHiddenInstanceProps
544
+ }
545
+ };
546
+ let containerFiber = TestReconciler.createContainer(container, ConcurrentRoot, null, options?.isStrictMode ?? false, false, options?.identifierPrefix ?? "", options?.onUncaughtError ?? defaultOnUncaughtError, options?.onCaughtError ?? defaultOnCaughtError, options?.onRecoverableError ?? defaultOnRecoverableError, null);
547
+ measureEnd("createRoot");
548
+ const render = (element) => {
549
+ if (containerFiber == null) throw new Error("Cannot render after unmount");
550
+ measureStart("render");
551
+ try {
552
+ TestReconciler.updateContainer(element, containerFiber, null, null);
553
+ } finally {
554
+ measureEnd("render", { elementType: String(element.type) });
555
+ }
556
+ };
557
+ const unmount = () => {
558
+ if (container == null) return;
559
+ measureStart("unmount");
560
+ try {
561
+ TestReconciler.updateContainer(null, containerFiber, null, null);
562
+ } finally {
563
+ measureEnd("unmount");
564
+ }
565
+ containerFiber = null;
566
+ container = null;
567
+ };
568
+ return {
569
+ render,
570
+ unmount,
571
+ get container() {
572
+ if (container == null) throw new Error("Cannot access .container on unmounted test renderer");
573
+ return TestInstance.fromInstance(container);
574
+ }
575
+ };
833
576
  }
834
- export {
835
- createRoot
836
- };
577
+ //#endregion
578
+ export { createRoot };
579
+
837
580
  //# sourceMappingURL=index.js.map