@avgz/react-contract-renderer 0.1.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/README.md +233 -0
- package/dist/THIRD_PARTY_LICENSES.txt +334 -0
- package/dist/adapters/dom.d.cts +5 -0
- package/dist/adapters/dom.d.ts +5 -0
- package/dist/adapters/react17.cjs +18657 -0
- package/dist/adapters/react18.cjs +20627 -0
- package/dist/adapters/react19_0.cjs +20014 -0
- package/dist/adapters/react19_1.cjs +20319 -0
- package/dist/adapters/react19_2.cjs +22561 -0
- package/dist/adapters/react19_3.cjs +24506 -0
- package/dist/adapters/reconciler.d.cts +19 -0
- package/dist/adapters/reconciler.d.ts +19 -0
- package/dist/index.cjs +1010 -0
- package/dist/index.cjs.map +7 -0
- package/dist/index.d.cts +82 -0
- package/dist/index.d.ts +82 -0
- package/dist/index.js +2 -0
- package/dist/internal.d.cts +30 -0
- package/dist/internal.d.ts +30 -0
- package/dist/mount.d.cts +2 -0
- package/dist/mount.d.ts +2 -0
- package/dist/shallow.d.cts +2 -0
- package/dist/shallow.d.ts +2 -0
- package/dist/subject.d.cts +35 -0
- package/dist/subject.d.ts +35 -0
- package/package.json +86 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1010 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
RenderSession: () => RenderSession,
|
|
34
|
+
Subject: () => Subject,
|
|
35
|
+
cleanup: () => cleanup,
|
|
36
|
+
getComponentRenderer: () => getComponentRenderer
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(index_exports);
|
|
39
|
+
var import_react2 = require("react");
|
|
40
|
+
|
|
41
|
+
// src/mount.ts
|
|
42
|
+
var React = __toESM(require("react"), 1);
|
|
43
|
+
|
|
44
|
+
// src/adapters/dom.ts
|
|
45
|
+
function selectDOMReactVersion(version3) {
|
|
46
|
+
const match = /^(17|18|19)\.(\d+)\.(\d+)$/.exec(version3);
|
|
47
|
+
const major = Number(match?.[1]);
|
|
48
|
+
const minor = Number(match?.[2]);
|
|
49
|
+
const patch = Number(match?.[3]);
|
|
50
|
+
if (major === 17 && minor === 0 && patch === 2) return 17;
|
|
51
|
+
if (major === 18 && (minor === 2 || minor === 3)) return 18;
|
|
52
|
+
if (major === 19 && minor >= 0 && minor <= 3) return 19;
|
|
53
|
+
throw new Error(
|
|
54
|
+
`Unsupported React version ${version3}. Mount supports stable React 17.0.2, 18.2\u201318.3, and 19.0\u201319.3.`
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
function record(value) {
|
|
58
|
+
return typeof value === "object" && value !== null ? value : null;
|
|
59
|
+
}
|
|
60
|
+
function currentFiber(publicRoot) {
|
|
61
|
+
const root = record(publicRoot);
|
|
62
|
+
if (root === null)
|
|
63
|
+
throw new Error(
|
|
64
|
+
"Unsupported React DOM internals: expected a mounted root."
|
|
65
|
+
);
|
|
66
|
+
const internalRoot = record(root["_internalRoot"]);
|
|
67
|
+
if (internalRoot === null)
|
|
68
|
+
throw new Error("Unsupported React DOM internals: expected a FiberRoot.");
|
|
69
|
+
const current = record(internalRoot["current"]);
|
|
70
|
+
if (current === null || current["tag"] !== 3) {
|
|
71
|
+
throw new Error(
|
|
72
|
+
"Unsupported React DOM internals: expected FiberRoot.current."
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
return current;
|
|
76
|
+
}
|
|
77
|
+
function skipped(fiber, version3) {
|
|
78
|
+
if (fiber.tag === 4 || fiber.tag === 18) return true;
|
|
79
|
+
const offscreen = version3 === 17 ? 23 : 22;
|
|
80
|
+
const legacyHidden = version3 === 17 ? 24 : 23;
|
|
81
|
+
return (fiber.tag === offscreen || fiber.tag === legacyHidden) && fiber.memoizedState !== null;
|
|
82
|
+
}
|
|
83
|
+
function isHost(fiber, version3) {
|
|
84
|
+
return fiber.tag === 5 || version3 === 19 && (fiber.tag === 26 || fiber.tag === 27);
|
|
85
|
+
}
|
|
86
|
+
function exposedType(fiber, version3) {
|
|
87
|
+
if (isHost(fiber, version3)) return fiber.type;
|
|
88
|
+
switch (fiber.tag) {
|
|
89
|
+
case 0:
|
|
90
|
+
// Function.
|
|
91
|
+
case 1:
|
|
92
|
+
return fiber.type;
|
|
93
|
+
case 11:
|
|
94
|
+
// ForwardRef.
|
|
95
|
+
case 14:
|
|
96
|
+
return fiber.type;
|
|
97
|
+
case 15:
|
|
98
|
+
return fiber.elementType;
|
|
99
|
+
default:
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function hostElement(fiber) {
|
|
104
|
+
const node = record(fiber.stateNode);
|
|
105
|
+
return node?.["nodeType"] === 1 ? fiber.stateNode : null;
|
|
106
|
+
}
|
|
107
|
+
function firstDOM(fiber, version3) {
|
|
108
|
+
if (skipped(fiber, version3)) return null;
|
|
109
|
+
if (isHost(fiber, version3)) return hostElement(fiber);
|
|
110
|
+
for (let { child } = fiber; child !== null; child = child.sibling) {
|
|
111
|
+
const element = firstDOM(child, version3);
|
|
112
|
+
if (element !== null) return element;
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
function committedText(fiber, version3) {
|
|
117
|
+
if (skipped(fiber, version3)) return "";
|
|
118
|
+
if (fiber.tag === 6) {
|
|
119
|
+
const node = record(fiber.stateNode);
|
|
120
|
+
return typeof node?.["nodeValue"] === "string" ? node["nodeValue"] : "";
|
|
121
|
+
}
|
|
122
|
+
if (isHost(fiber, version3) && fiber.child === null)
|
|
123
|
+
return hostElement(fiber)?.textContent ?? "";
|
|
124
|
+
let text = "";
|
|
125
|
+
for (let { child } = fiber; child !== null; child = child.sibling) {
|
|
126
|
+
text += committedText(child, version3);
|
|
127
|
+
}
|
|
128
|
+
return text;
|
|
129
|
+
}
|
|
130
|
+
var CommittedNode = class {
|
|
131
|
+
constructor(fiber, type, version3) {
|
|
132
|
+
this.fiber = fiber;
|
|
133
|
+
this.type = type;
|
|
134
|
+
this.version = version3;
|
|
135
|
+
}
|
|
136
|
+
get props() {
|
|
137
|
+
return record(this.fiber.memoizedProps) ?? {};
|
|
138
|
+
}
|
|
139
|
+
get children() {
|
|
140
|
+
const children = [];
|
|
141
|
+
appendChildren(this.fiber.child, this.version, children);
|
|
142
|
+
return children;
|
|
143
|
+
}
|
|
144
|
+
get text() {
|
|
145
|
+
return committedText(this.fiber, this.version);
|
|
146
|
+
}
|
|
147
|
+
get dom() {
|
|
148
|
+
return firstDOM(this.fiber, this.version);
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
function appendChildren(first, version3, output) {
|
|
152
|
+
for (let fiber = first; fiber !== null; fiber = fiber.sibling) {
|
|
153
|
+
if (skipped(fiber, version3)) continue;
|
|
154
|
+
const type = exposedType(fiber, version3);
|
|
155
|
+
if (type === null) appendChildren(fiber.child, version3, output);
|
|
156
|
+
else output.push(new CommittedNode(fiber, type, version3));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function findBoundary(first, boundary, version3) {
|
|
160
|
+
for (let fiber = first; fiber !== null; fiber = fiber.sibling) {
|
|
161
|
+
if (skipped(fiber, version3)) continue;
|
|
162
|
+
if (fiber.elementType === boundary || fiber.type === boundary) return fiber;
|
|
163
|
+
const found = findBoundary(fiber.child, boundary, version3);
|
|
164
|
+
if (found !== null) return found;
|
|
165
|
+
}
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
function inspectDOMRoot(version3, container, publicRoot, boundary) {
|
|
169
|
+
const root = version3 === 17 ? record(container)?.["_reactRootContainer"] : publicRoot;
|
|
170
|
+
const current = currentFiber(root);
|
|
171
|
+
const targetBoundary = findBoundary(current.child, boundary, version3);
|
|
172
|
+
if (targetBoundary === null) return null;
|
|
173
|
+
return new CommittedNode(targetBoundary, boundary, version3);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// src/internal.ts
|
|
177
|
+
var actScopes = 0;
|
|
178
|
+
var previousActEnvironment;
|
|
179
|
+
function enterActEnvironment() {
|
|
180
|
+
if (actScopes === 0) {
|
|
181
|
+
previousActEnvironment = Object.getOwnPropertyDescriptor(
|
|
182
|
+
globalThis,
|
|
183
|
+
"IS_REACT_ACT_ENVIRONMENT"
|
|
184
|
+
);
|
|
185
|
+
Object.defineProperty(globalThis, "IS_REACT_ACT_ENVIRONMENT", {
|
|
186
|
+
configurable: true,
|
|
187
|
+
enumerable: true,
|
|
188
|
+
writable: true,
|
|
189
|
+
value: true
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
actScopes += 1;
|
|
193
|
+
}
|
|
194
|
+
function leaveActEnvironment() {
|
|
195
|
+
actScopes -= 1;
|
|
196
|
+
if (actScopes !== 0) return;
|
|
197
|
+
if (previousActEnvironment === void 0) {
|
|
198
|
+
Reflect.deleteProperty(globalThis, "IS_REACT_ACT_ENVIRONMENT");
|
|
199
|
+
} else {
|
|
200
|
+
Object.defineProperty(
|
|
201
|
+
globalThis,
|
|
202
|
+
"IS_REACT_ACT_ENVIRONMENT",
|
|
203
|
+
previousActEnvironment
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
previousActEnvironment = void 0;
|
|
207
|
+
}
|
|
208
|
+
function wrap(element, wrappers, create) {
|
|
209
|
+
let result = element;
|
|
210
|
+
for (let index = wrappers.length - 1; index >= 0; index -= 1) {
|
|
211
|
+
const wrapper = wrappers[index];
|
|
212
|
+
if (wrapper !== void 0) result = create(wrapper, { children: result });
|
|
213
|
+
}
|
|
214
|
+
return result;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// src/mount.ts
|
|
218
|
+
var cachedRuntime;
|
|
219
|
+
function loadRuntime() {
|
|
220
|
+
const version3 = selectDOMReactVersion(React.version);
|
|
221
|
+
const reactRuntime = React;
|
|
222
|
+
const utilities = typeof reactRuntime["act"] === "function" ? reactRuntime : require("react-dom/test-utils");
|
|
223
|
+
const actCandidate = utilities["act"];
|
|
224
|
+
if (typeof actCandidate !== "function")
|
|
225
|
+
throw new Error(
|
|
226
|
+
"This React build does not provide act(). Use a development React build for testing."
|
|
227
|
+
);
|
|
228
|
+
const reactAct = actCandidate;
|
|
229
|
+
const legacy = version3 === 17 ? require("react-dom") : null;
|
|
230
|
+
const concurrent = version3 === 17 ? null : require("react-dom");
|
|
231
|
+
const domVersion = legacy?.version ?? concurrent?.version;
|
|
232
|
+
if (domVersion !== React.version) {
|
|
233
|
+
throw new Error(
|
|
234
|
+
`React and React DOM versions must match; received React ${React.version} and React DOM ${String(domVersion)}.`
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
const client = version3 === 17 ? null : require("react-dom/client");
|
|
238
|
+
return { version: version3, reactAct, legacy, concurrent, client };
|
|
239
|
+
}
|
|
240
|
+
function createMountDriver(options) {
|
|
241
|
+
if (typeof document === "undefined" || document.body === null) {
|
|
242
|
+
throw new Error(
|
|
243
|
+
"mount() requires a DOM document with a body. Configure jsdom before mounting."
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
const { version: version3, reactAct, legacy, client } = cachedRuntime ??= loadRuntime();
|
|
247
|
+
const container = document.createElement("div");
|
|
248
|
+
let root = null;
|
|
249
|
+
let unmounted = false;
|
|
250
|
+
let currentProps = options.props;
|
|
251
|
+
let currentWrappers = options.wrappers;
|
|
252
|
+
let { initialElement } = options;
|
|
253
|
+
const pendingErrors = [];
|
|
254
|
+
function throwPendingErrors() {
|
|
255
|
+
if (pendingErrors.length === 0) return;
|
|
256
|
+
if (pendingErrors.length === 1) throw pendingErrors.shift();
|
|
257
|
+
const errors = pendingErrors.splice(0);
|
|
258
|
+
throw new AggregateError(errors, "Multiple uncaught React errors.");
|
|
259
|
+
}
|
|
260
|
+
function sync(callback) {
|
|
261
|
+
enterActEnvironment();
|
|
262
|
+
try {
|
|
263
|
+
reactAct(callback);
|
|
264
|
+
throwPendingErrors();
|
|
265
|
+
} finally {
|
|
266
|
+
leaveActEnvironment();
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
const driver = {
|
|
270
|
+
mode: "mount",
|
|
271
|
+
inspect() {
|
|
272
|
+
throwPendingErrors();
|
|
273
|
+
return unmounted ? null : inspectDOMRoot(version3, container, root, options.component);
|
|
274
|
+
},
|
|
275
|
+
render(props, wrappers) {
|
|
276
|
+
if (unmounted) throw new Error("Cannot render an unmounted subject.");
|
|
277
|
+
currentProps = props;
|
|
278
|
+
currentWrappers = wrappers;
|
|
279
|
+
const target = initialElement ?? React.createElement(options.component, props);
|
|
280
|
+
initialElement = void 0;
|
|
281
|
+
const element = wrap(
|
|
282
|
+
target,
|
|
283
|
+
wrappers,
|
|
284
|
+
(type, providerProps) => React.createElement(type, providerProps)
|
|
285
|
+
);
|
|
286
|
+
sync(() => {
|
|
287
|
+
if (legacy !== null) legacy.render(element, container);
|
|
288
|
+
else if (root !== null) root.render(element);
|
|
289
|
+
else throw new Error("React DOM root was not initialized.");
|
|
290
|
+
});
|
|
291
|
+
},
|
|
292
|
+
flush() {
|
|
293
|
+
if (!unmounted) driver.render(currentProps, currentWrappers);
|
|
294
|
+
},
|
|
295
|
+
async act(callback) {
|
|
296
|
+
if (unmounted) throw new Error("Cannot act on an unmounted subject.");
|
|
297
|
+
enterActEnvironment();
|
|
298
|
+
try {
|
|
299
|
+
await reactAct(async () => {
|
|
300
|
+
await callback();
|
|
301
|
+
});
|
|
302
|
+
throwPendingErrors();
|
|
303
|
+
} finally {
|
|
304
|
+
leaveActEnvironment();
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
unmount() {
|
|
308
|
+
if (unmounted) return;
|
|
309
|
+
unmounted = true;
|
|
310
|
+
try {
|
|
311
|
+
sync(() => {
|
|
312
|
+
if (legacy !== null) legacy.unmountComponentAtNode(container);
|
|
313
|
+
else root?.unmount();
|
|
314
|
+
});
|
|
315
|
+
} finally {
|
|
316
|
+
root = null;
|
|
317
|
+
container.remove();
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
document.body.appendChild(container);
|
|
322
|
+
try {
|
|
323
|
+
if (client !== null) {
|
|
324
|
+
root = version3 === 19 ? client.createRoot(container, {
|
|
325
|
+
onUncaughtError: (error) => {
|
|
326
|
+
pendingErrors.push(error);
|
|
327
|
+
}
|
|
328
|
+
}) : client.createRoot(container);
|
|
329
|
+
}
|
|
330
|
+
driver.render(options.props, options.wrappers);
|
|
331
|
+
} catch (error) {
|
|
332
|
+
try {
|
|
333
|
+
driver.unmount();
|
|
334
|
+
} catch (cleanupError) {
|
|
335
|
+
throw new AggregateError(
|
|
336
|
+
[error, cleanupError],
|
|
337
|
+
"Mount failed and React cleanup also failed."
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
throw error;
|
|
341
|
+
}
|
|
342
|
+
return driver;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// src/shallow.ts
|
|
346
|
+
var React3 = __toESM(require("react"), 1);
|
|
347
|
+
|
|
348
|
+
// src/adapters/reconciler.ts
|
|
349
|
+
var React2 = __toESM(require("react"), 1);
|
|
350
|
+
var noop = () => {
|
|
351
|
+
};
|
|
352
|
+
var emptyContext = Object.freeze({});
|
|
353
|
+
var instance;
|
|
354
|
+
var cachedAct;
|
|
355
|
+
function reactVersion() {
|
|
356
|
+
const match = /^(17|18|19)\.(\d+)\.(\d+)$/.exec(React2.version);
|
|
357
|
+
const major = Number(match?.[1]);
|
|
358
|
+
const minor = Number(match?.[2]);
|
|
359
|
+
if (!match || major === 17 && minor !== 0 || major === 18 && (minor < 2 || minor > 3) || major === 19 && minor > 3) {
|
|
360
|
+
throw new Error(
|
|
361
|
+
`Unsupported React ${React2.version}; tested adapters cover 17.0.2, 18.2\u201318.3, and 19.0\u201319.3 stable releases.`
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
return { major, minor };
|
|
365
|
+
}
|
|
366
|
+
function loadFactory(major, minor) {
|
|
367
|
+
switch (major) {
|
|
368
|
+
case 17:
|
|
369
|
+
return require("./adapters/react17.cjs");
|
|
370
|
+
case 18:
|
|
371
|
+
return require("./adapters/react18.cjs");
|
|
372
|
+
case 19:
|
|
373
|
+
switch (minor) {
|
|
374
|
+
case 0:
|
|
375
|
+
return require("./adapters/react19_0.cjs");
|
|
376
|
+
case 1:
|
|
377
|
+
return require("./adapters/react19_1.cjs");
|
|
378
|
+
case 2:
|
|
379
|
+
return require("./adapters/react19_2.cjs");
|
|
380
|
+
case 3:
|
|
381
|
+
return require("./adapters/react19_3.cjs");
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
throw new Error(`No reconciler adapter for React ${React2.version}`);
|
|
385
|
+
}
|
|
386
|
+
function remove(parent, child) {
|
|
387
|
+
const index = parent.children.indexOf(child);
|
|
388
|
+
if (index >= 0) parent.children.splice(index, 1);
|
|
389
|
+
}
|
|
390
|
+
function append(parent, child) {
|
|
391
|
+
remove(parent, child);
|
|
392
|
+
parent.children.push(child);
|
|
393
|
+
}
|
|
394
|
+
function insert(parent, child, before) {
|
|
395
|
+
remove(parent, child);
|
|
396
|
+
const index = parent.children.indexOf(before);
|
|
397
|
+
if (index < 0)
|
|
398
|
+
throw new Error("Invalid insertion point in shallow host tree");
|
|
399
|
+
parent.children.splice(index, 0, child);
|
|
400
|
+
}
|
|
401
|
+
function getReconciler() {
|
|
402
|
+
if (instance) return instance;
|
|
403
|
+
const { major, minor } = reactVersion();
|
|
404
|
+
let priority = 0;
|
|
405
|
+
const config = {
|
|
406
|
+
rendererVersion: "0.1.0",
|
|
407
|
+
rendererPackageName: "@avgz/react-contract-renderer",
|
|
408
|
+
isPrimaryRenderer: false,
|
|
409
|
+
supportsMutation: true,
|
|
410
|
+
supportsPersistence: false,
|
|
411
|
+
supportsHydration: false,
|
|
412
|
+
supportsMicrotasks: true,
|
|
413
|
+
supportsResources: false,
|
|
414
|
+
supportsSingletons: false,
|
|
415
|
+
supportsTestSelectors: false,
|
|
416
|
+
getRootHostContext: () => emptyContext,
|
|
417
|
+
getChildHostContext: () => emptyContext,
|
|
418
|
+
getPublicInstance: (node) => node,
|
|
419
|
+
prepareForCommit: () => null,
|
|
420
|
+
resetAfterCommit: noop,
|
|
421
|
+
createInstance: (type, props) => ({
|
|
422
|
+
type,
|
|
423
|
+
props,
|
|
424
|
+
children: [],
|
|
425
|
+
hidden: false
|
|
426
|
+
}),
|
|
427
|
+
createTextInstance: (text) => ({
|
|
428
|
+
type: "#text",
|
|
429
|
+
props: { text },
|
|
430
|
+
children: [],
|
|
431
|
+
hidden: false
|
|
432
|
+
}),
|
|
433
|
+
appendInitialChild: append,
|
|
434
|
+
appendChild: append,
|
|
435
|
+
appendChildToContainer: append,
|
|
436
|
+
insertBefore: insert,
|
|
437
|
+
insertInContainerBefore: insert,
|
|
438
|
+
removeChild: remove,
|
|
439
|
+
removeChildFromContainer: remove,
|
|
440
|
+
clearContainer: (container) => {
|
|
441
|
+
container.children.length = 0;
|
|
442
|
+
},
|
|
443
|
+
finalizeInitialChildren: () => false,
|
|
444
|
+
shouldSetTextContent: () => false,
|
|
445
|
+
prepareUpdate: () => true,
|
|
446
|
+
commitUpdate: major >= 19 ? (node, _type, _old, props) => {
|
|
447
|
+
node.props = props;
|
|
448
|
+
} : (node, _payload, _type, _old, props) => {
|
|
449
|
+
node.props = props;
|
|
450
|
+
},
|
|
451
|
+
commitTextUpdate: (node, _old, text) => {
|
|
452
|
+
node.props = { text };
|
|
453
|
+
},
|
|
454
|
+
resetTextContent: (node) => {
|
|
455
|
+
node.children.length = 0;
|
|
456
|
+
},
|
|
457
|
+
hideInstance: (node) => {
|
|
458
|
+
node.hidden = true;
|
|
459
|
+
},
|
|
460
|
+
unhideInstance: (node) => {
|
|
461
|
+
node.hidden = false;
|
|
462
|
+
},
|
|
463
|
+
hideTextInstance: (node) => {
|
|
464
|
+
node.hidden = true;
|
|
465
|
+
},
|
|
466
|
+
unhideTextInstance: (node) => {
|
|
467
|
+
node.hidden = false;
|
|
468
|
+
},
|
|
469
|
+
detachDeletedInstance: (node) => {
|
|
470
|
+
node.children.length = 0;
|
|
471
|
+
},
|
|
472
|
+
preparePortalMount: noop,
|
|
473
|
+
now: () => performance.now(),
|
|
474
|
+
scheduleTimeout: setTimeout,
|
|
475
|
+
cancelTimeout: clearTimeout,
|
|
476
|
+
noTimeout: -1,
|
|
477
|
+
scheduleMicrotask: queueMicrotask,
|
|
478
|
+
getCurrentEventPriority: () => 16,
|
|
479
|
+
getCurrentUpdatePriority: () => priority,
|
|
480
|
+
setCurrentUpdatePriority: (next) => {
|
|
481
|
+
priority = next;
|
|
482
|
+
},
|
|
483
|
+
resolveUpdatePriority: () => priority || 32,
|
|
484
|
+
shouldAttemptEagerTransition: () => false,
|
|
485
|
+
trackSchedulerEvent: noop,
|
|
486
|
+
resolveEventType: () => null,
|
|
487
|
+
resolveEventTimeStamp: () => -1.1,
|
|
488
|
+
maySuspendCommit: () => false,
|
|
489
|
+
maySuspendCommitOnUpdate: () => false,
|
|
490
|
+
maySuspendCommitInSyncRender: () => false,
|
|
491
|
+
preloadInstance: () => true,
|
|
492
|
+
NotPendingTransition: null,
|
|
493
|
+
HostTransitionContext: React2.createContext(null)
|
|
494
|
+
};
|
|
495
|
+
instance = loadFactory(major, minor)(config);
|
|
496
|
+
return instance;
|
|
497
|
+
}
|
|
498
|
+
function actFunction() {
|
|
499
|
+
if (cachedAct) return cachedAct;
|
|
500
|
+
const react = React2;
|
|
501
|
+
if (react.act) cachedAct = react.act;
|
|
502
|
+
else if (reactVersion().major === 18) {
|
|
503
|
+
const utilities = require("react-dom/test-utils");
|
|
504
|
+
cachedAct = utilities.act;
|
|
505
|
+
}
|
|
506
|
+
return cachedAct;
|
|
507
|
+
}
|
|
508
|
+
function createShallowRoot() {
|
|
509
|
+
const reconciler = getReconciler();
|
|
510
|
+
const { major } = reactVersion();
|
|
511
|
+
const container = {
|
|
512
|
+
type: "#root",
|
|
513
|
+
props: {},
|
|
514
|
+
children: [],
|
|
515
|
+
hidden: false
|
|
516
|
+
};
|
|
517
|
+
let failure;
|
|
518
|
+
const onError = (error) => {
|
|
519
|
+
failure = { error };
|
|
520
|
+
};
|
|
521
|
+
const root = major === 17 ? reconciler.createContainer(container, 0, false, null) : major === 18 ? reconciler.createContainer(
|
|
522
|
+
container,
|
|
523
|
+
1,
|
|
524
|
+
null,
|
|
525
|
+
false,
|
|
526
|
+
null,
|
|
527
|
+
"",
|
|
528
|
+
onError,
|
|
529
|
+
null
|
|
530
|
+
) : reconciler.createContainer(
|
|
531
|
+
container,
|
|
532
|
+
1,
|
|
533
|
+
null,
|
|
534
|
+
false,
|
|
535
|
+
null,
|
|
536
|
+
"",
|
|
537
|
+
onError,
|
|
538
|
+
onError,
|
|
539
|
+
onError,
|
|
540
|
+
noop
|
|
541
|
+
);
|
|
542
|
+
const checkError = () => {
|
|
543
|
+
if (failure) {
|
|
544
|
+
const { error } = failure;
|
|
545
|
+
failure = void 0;
|
|
546
|
+
throw error;
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
const flushSync = reconciler.flushSync ?? reconciler.flushSyncFromReconciler;
|
|
550
|
+
if (!flushSync)
|
|
551
|
+
throw new Error(
|
|
552
|
+
`React ${React2.version} reconciler has no synchronous flush API`
|
|
553
|
+
);
|
|
554
|
+
const drain = () => {
|
|
555
|
+
let passes = 0;
|
|
556
|
+
do {
|
|
557
|
+
flushSync(noop);
|
|
558
|
+
checkError();
|
|
559
|
+
if (++passes > 100)
|
|
560
|
+
throw new Error("Shallow effects did not settle after 100 flushes");
|
|
561
|
+
} while (reconciler.flushPassiveEffects());
|
|
562
|
+
checkError();
|
|
563
|
+
};
|
|
564
|
+
const sync = (callback) => {
|
|
565
|
+
const act = actFunction();
|
|
566
|
+
if (act) {
|
|
567
|
+
enterActEnvironment();
|
|
568
|
+
try {
|
|
569
|
+
void act(() => {
|
|
570
|
+
callback();
|
|
571
|
+
drain();
|
|
572
|
+
});
|
|
573
|
+
} finally {
|
|
574
|
+
leaveActEnvironment();
|
|
575
|
+
}
|
|
576
|
+
} else {
|
|
577
|
+
callback();
|
|
578
|
+
drain();
|
|
579
|
+
}
|
|
580
|
+
checkError();
|
|
581
|
+
};
|
|
582
|
+
return {
|
|
583
|
+
container,
|
|
584
|
+
render(element) {
|
|
585
|
+
sync(
|
|
586
|
+
() => flushSync(() => {
|
|
587
|
+
(reconciler.updateContainerSync ?? reconciler.updateContainer)(
|
|
588
|
+
element,
|
|
589
|
+
root,
|
|
590
|
+
null,
|
|
591
|
+
null
|
|
592
|
+
);
|
|
593
|
+
})
|
|
594
|
+
);
|
|
595
|
+
},
|
|
596
|
+
flush() {
|
|
597
|
+
sync(noop);
|
|
598
|
+
},
|
|
599
|
+
async act(callback) {
|
|
600
|
+
const act = actFunction();
|
|
601
|
+
if (act) {
|
|
602
|
+
enterActEnvironment();
|
|
603
|
+
try {
|
|
604
|
+
await act(async () => {
|
|
605
|
+
await callback();
|
|
606
|
+
drain();
|
|
607
|
+
});
|
|
608
|
+
} finally {
|
|
609
|
+
leaveActEnvironment();
|
|
610
|
+
}
|
|
611
|
+
} else {
|
|
612
|
+
await callback();
|
|
613
|
+
drain();
|
|
614
|
+
}
|
|
615
|
+
checkError();
|
|
616
|
+
}
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
// src/shallow.ts
|
|
621
|
+
var outputType = "contract-renderer-output";
|
|
622
|
+
var wrappedTypes = /* @__PURE__ */ new WeakMap();
|
|
623
|
+
var noChildren = Object.freeze([]);
|
|
624
|
+
function capture(value, props) {
|
|
625
|
+
return React3.createElement(outputType, { value, input: props });
|
|
626
|
+
}
|
|
627
|
+
function instrument(type) {
|
|
628
|
+
if (typeof type === "string") {
|
|
629
|
+
return (props) => capture(props["children"], props);
|
|
630
|
+
}
|
|
631
|
+
const existing = wrappedTypes.get(type);
|
|
632
|
+
if (existing) return existing;
|
|
633
|
+
let result;
|
|
634
|
+
if (typeof type === "function") {
|
|
635
|
+
if (type.prototype && "isReactComponent" in type.prototype) {
|
|
636
|
+
const Base = type;
|
|
637
|
+
result = class ContractTarget extends Base {
|
|
638
|
+
render() {
|
|
639
|
+
return capture(super.render(), this.props);
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
} else {
|
|
643
|
+
const render = type;
|
|
644
|
+
result = (props) => capture(render(props), props);
|
|
645
|
+
if ("defaultProps" in type)
|
|
646
|
+
Object.assign(result, { defaultProps: type.defaultProps });
|
|
647
|
+
}
|
|
648
|
+
} else {
|
|
649
|
+
const exotic = type;
|
|
650
|
+
switch (exotic.$$typeof) {
|
|
651
|
+
case Symbol.for("react.memo"): {
|
|
652
|
+
if (!exotic.type) throw new TypeError("Invalid memo component");
|
|
653
|
+
const child = instrument(exotic.type);
|
|
654
|
+
result = React3.memo(child, exotic.compare);
|
|
655
|
+
break;
|
|
656
|
+
}
|
|
657
|
+
case Symbol.for("react.forward_ref"): {
|
|
658
|
+
const { render } = exotic;
|
|
659
|
+
if (!render) throw new TypeError("Invalid forwardRef component");
|
|
660
|
+
result = React3.forwardRef(
|
|
661
|
+
(props, ref) => capture(render(props, ref), props)
|
|
662
|
+
);
|
|
663
|
+
break;
|
|
664
|
+
}
|
|
665
|
+
case Symbol.for("react.lazy"): {
|
|
666
|
+
const initialize = exotic._init;
|
|
667
|
+
if (!initialize) throw new TypeError("Invalid lazy component");
|
|
668
|
+
result = (props) => React3.createElement(instrument(initialize(exotic._payload)), props);
|
|
669
|
+
break;
|
|
670
|
+
}
|
|
671
|
+
default:
|
|
672
|
+
throw new TypeError(
|
|
673
|
+
"Shallow rendering requires a component function, class, memo, forwardRef, lazy component, or host tag"
|
|
674
|
+
);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
wrappedTypes.set(type, result);
|
|
678
|
+
return result;
|
|
679
|
+
}
|
|
680
|
+
function outputNode(node) {
|
|
681
|
+
if (node.hidden) return void 0;
|
|
682
|
+
if (node.type === outputType) return node;
|
|
683
|
+
for (const child of node.children) {
|
|
684
|
+
const found = outputNode(child);
|
|
685
|
+
if (found) return found;
|
|
686
|
+
}
|
|
687
|
+
return void 0;
|
|
688
|
+
}
|
|
689
|
+
function inspectChildren(value) {
|
|
690
|
+
const children = [];
|
|
691
|
+
let text = "";
|
|
692
|
+
React3.Children.forEach(value, (child) => {
|
|
693
|
+
if (typeof child === "string" || typeof child === "number" || typeof child === "bigint") {
|
|
694
|
+
text += String(child);
|
|
695
|
+
} else if (React3.isValidElement(child)) {
|
|
696
|
+
const { type } = child;
|
|
697
|
+
if (type === React3.Fragment) {
|
|
698
|
+
const inner = inspectChildren(child.props["children"]);
|
|
699
|
+
children.push(...inner.children);
|
|
700
|
+
text += inner.text;
|
|
701
|
+
} else {
|
|
702
|
+
const inner = typeof type === "string" ? inspectChildren(child.props["children"]) : { children: noChildren, text: "" };
|
|
703
|
+
children.push({
|
|
704
|
+
type,
|
|
705
|
+
props: child.props,
|
|
706
|
+
children: inner.children,
|
|
707
|
+
text: inner.text,
|
|
708
|
+
dom: null
|
|
709
|
+
});
|
|
710
|
+
text += inner.text;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
});
|
|
714
|
+
return { children, text };
|
|
715
|
+
}
|
|
716
|
+
function createShallowDriver(options) {
|
|
717
|
+
const root = createShallowRoot();
|
|
718
|
+
const Target = instrument(options.component);
|
|
719
|
+
let disposed = false;
|
|
720
|
+
let currentProps = options.props;
|
|
721
|
+
let currentWrappers = options.wrappers;
|
|
722
|
+
const driver = {
|
|
723
|
+
mode: "shallow",
|
|
724
|
+
inspect() {
|
|
725
|
+
if (disposed) return null;
|
|
726
|
+
const node = outputNode(root.container);
|
|
727
|
+
if (!node) return null;
|
|
728
|
+
const children = inspectChildren(node.props["value"]);
|
|
729
|
+
return {
|
|
730
|
+
type: options.component,
|
|
731
|
+
props: node.props["input"],
|
|
732
|
+
children: children.children,
|
|
733
|
+
text: children.text,
|
|
734
|
+
dom: null
|
|
735
|
+
};
|
|
736
|
+
},
|
|
737
|
+
render(props, wrappers) {
|
|
738
|
+
if (disposed) throw new Error("Cannot render an unmounted subject");
|
|
739
|
+
currentProps = props;
|
|
740
|
+
currentWrappers = wrappers;
|
|
741
|
+
const target = React3.createElement(Target, props);
|
|
742
|
+
root.render(wrap(target, wrappers, React3.createElement));
|
|
743
|
+
},
|
|
744
|
+
flush() {
|
|
745
|
+
if (disposed) throw new Error("Cannot flush an unmounted subject");
|
|
746
|
+
driver.render(currentProps, currentWrappers);
|
|
747
|
+
},
|
|
748
|
+
async act(callback) {
|
|
749
|
+
if (disposed) throw new Error("Cannot update an unmounted subject");
|
|
750
|
+
await root.act(callback);
|
|
751
|
+
},
|
|
752
|
+
unmount() {
|
|
753
|
+
if (disposed) return;
|
|
754
|
+
disposed = true;
|
|
755
|
+
root.render(null);
|
|
756
|
+
}
|
|
757
|
+
};
|
|
758
|
+
try {
|
|
759
|
+
driver.render(options.props, options.wrappers);
|
|
760
|
+
} catch (error) {
|
|
761
|
+
driver.unmount();
|
|
762
|
+
throw error;
|
|
763
|
+
}
|
|
764
|
+
return driver;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
// src/subject.ts
|
|
768
|
+
var import_react = require("react");
|
|
769
|
+
function validateType(type) {
|
|
770
|
+
if (typeof type === "string") {
|
|
771
|
+
if (!/^[a-zA-Z][a-zA-Z0-9:_-]*$/.test(type)) {
|
|
772
|
+
throw new TypeError(
|
|
773
|
+
"Subject queries accept an intrinsic tag name, not a CSS selector."
|
|
774
|
+
);
|
|
775
|
+
}
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
if (typeof type === "function") return;
|
|
779
|
+
const marker = typeof type === "object" && type !== null && "$$typeof" in type ? type.$$typeof : type;
|
|
780
|
+
if (typeof marker === "symbol") {
|
|
781
|
+
const name = Symbol.keyFor(marker);
|
|
782
|
+
if (name === "react.memo" || name === "react.forward_ref" || name === "react.lazy" || name === "react.context" || name === "react.provider" || name === "react.consumer" || name === "react.fragment" || name === "react.strict_mode" || name === "react.profiler" || name === "react.suspense" || name === "react.suspense_list" || name === "react.activity")
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
throw new TypeError(
|
|
786
|
+
"Subject queries require a React component identity or an intrinsic tag name."
|
|
787
|
+
);
|
|
788
|
+
}
|
|
789
|
+
function collectMatches(node, type, matches) {
|
|
790
|
+
if (node.type === type) matches.push(node);
|
|
791
|
+
for (const child of node.children) collectMatches(child, type, matches);
|
|
792
|
+
}
|
|
793
|
+
var Subject = class _Subject {
|
|
794
|
+
/** @internal */
|
|
795
|
+
constructor(source, mode) {
|
|
796
|
+
this.source = source;
|
|
797
|
+
this.mode = mode;
|
|
798
|
+
}
|
|
799
|
+
/** Match a component identity or host tag, including this node; inspection rejects multiple matches. */
|
|
800
|
+
find(type) {
|
|
801
|
+
validateType(type);
|
|
802
|
+
this.resolve();
|
|
803
|
+
return new _Subject(() => this.search(type), this.mode);
|
|
804
|
+
}
|
|
805
|
+
/** Return live selections by match index. Re-query after insertion/reordering to obtain a new list. */
|
|
806
|
+
findAll(type) {
|
|
807
|
+
validateType(type);
|
|
808
|
+
return this.search(type).map(
|
|
809
|
+
(_, index) => new _Subject(() => {
|
|
810
|
+
const node = this.search(type)[index];
|
|
811
|
+
return node === void 0 ? [] : [node];
|
|
812
|
+
}, this.mode)
|
|
813
|
+
);
|
|
814
|
+
}
|
|
815
|
+
/** Report whether exactly one matching node exists in the current render. */
|
|
816
|
+
exists() {
|
|
817
|
+
return this.resolve() !== void 0;
|
|
818
|
+
}
|
|
819
|
+
/** Return every prop from the selected component or host node. */
|
|
820
|
+
props() {
|
|
821
|
+
return this.requireNode().props;
|
|
822
|
+
}
|
|
823
|
+
/** Return one typed prop from the selected component or host node. */
|
|
824
|
+
prop(key) {
|
|
825
|
+
return this.props()[key];
|
|
826
|
+
}
|
|
827
|
+
/** Return the selected node's string className, if it has one. */
|
|
828
|
+
className() {
|
|
829
|
+
const value = this.requireNode().props["className"];
|
|
830
|
+
if (value === void 0) return void 0;
|
|
831
|
+
if (typeof value !== "string") {
|
|
832
|
+
throw new TypeError(
|
|
833
|
+
"The selected node has a className prop that is not a string."
|
|
834
|
+
);
|
|
835
|
+
}
|
|
836
|
+
return value;
|
|
837
|
+
}
|
|
838
|
+
/** Return the selected component identity or intrinsic host tag. */
|
|
839
|
+
type() {
|
|
840
|
+
return this.requireNode().type;
|
|
841
|
+
}
|
|
842
|
+
/** Recreate the selected node as a React element with its current props. */
|
|
843
|
+
element() {
|
|
844
|
+
const node = this.requireNode();
|
|
845
|
+
return (0, import_react.createElement)(node.type, node.props);
|
|
846
|
+
}
|
|
847
|
+
/** Return all text content beneath the selected node. */
|
|
848
|
+
text() {
|
|
849
|
+
return this.requireNode().text;
|
|
850
|
+
}
|
|
851
|
+
/**
|
|
852
|
+
* Mount only: return the first host element represented by the selected
|
|
853
|
+
* contract.
|
|
854
|
+
*/
|
|
855
|
+
getDOMNode() {
|
|
856
|
+
const node = this.requireNode();
|
|
857
|
+
if (this.mode === "shallow") {
|
|
858
|
+
throw new Error(
|
|
859
|
+
"getDOMNode() is unavailable for shallow rendering; use mount() instead."
|
|
860
|
+
);
|
|
861
|
+
}
|
|
862
|
+
if (node.dom === null) {
|
|
863
|
+
throw new Error("The selected node has no associated host DOM element.");
|
|
864
|
+
}
|
|
865
|
+
return node.dom;
|
|
866
|
+
}
|
|
867
|
+
resolve() {
|
|
868
|
+
const nodes = this.source();
|
|
869
|
+
if (nodes.length > 1) {
|
|
870
|
+
throw new Error(
|
|
871
|
+
`Subject selection is ambiguous: found ${nodes.length} nodes. Use findAll() to select multiple nodes.`
|
|
872
|
+
);
|
|
873
|
+
}
|
|
874
|
+
return nodes[0];
|
|
875
|
+
}
|
|
876
|
+
requireNode() {
|
|
877
|
+
const node = this.resolve();
|
|
878
|
+
if (node === void 0) {
|
|
879
|
+
throw new Error(
|
|
880
|
+
"Subject selection is empty: no matching node exists in the current render."
|
|
881
|
+
);
|
|
882
|
+
}
|
|
883
|
+
return node;
|
|
884
|
+
}
|
|
885
|
+
search(type) {
|
|
886
|
+
const node = this.resolve();
|
|
887
|
+
if (node === void 0) return [];
|
|
888
|
+
const matches = [];
|
|
889
|
+
collectMatches(node, type, matches);
|
|
890
|
+
return matches;
|
|
891
|
+
}
|
|
892
|
+
};
|
|
893
|
+
|
|
894
|
+
// src/index.ts
|
|
895
|
+
var mounted = /* @__PURE__ */ new Set();
|
|
896
|
+
var RenderSession = class {
|
|
897
|
+
/**
|
|
898
|
+
* @internal
|
|
899
|
+
* Constructed by {@link getComponentRenderer}.
|
|
900
|
+
*/
|
|
901
|
+
constructor(component, props, factory, initialElement) {
|
|
902
|
+
this.component = component;
|
|
903
|
+
this.props = props;
|
|
904
|
+
this.factory = factory;
|
|
905
|
+
this.initialElement = initialElement;
|
|
906
|
+
}
|
|
907
|
+
driver;
|
|
908
|
+
wrappers = [];
|
|
909
|
+
disposed = false;
|
|
910
|
+
selection;
|
|
911
|
+
/**
|
|
912
|
+
* Configure providers before first observation. Providers nest in argument
|
|
913
|
+
* order, so the first provider is outermost.
|
|
914
|
+
*/
|
|
915
|
+
with(...providers) {
|
|
916
|
+
if (this.disposed) throw new Error("Cannot configure an unmounted subject");
|
|
917
|
+
if (this.driver)
|
|
918
|
+
throw new Error(
|
|
919
|
+
"Call .with(...) before observing or updating the subject"
|
|
920
|
+
);
|
|
921
|
+
this.wrappers = [...this.wrappers, ...providers];
|
|
922
|
+
return this;
|
|
923
|
+
}
|
|
924
|
+
/** Inspect the current render through live, typed contract queries. */
|
|
925
|
+
get subject() {
|
|
926
|
+
const driver = this.initialize();
|
|
927
|
+
this.selection ??= new Subject(() => {
|
|
928
|
+
const node = driver.inspect();
|
|
929
|
+
return node ? [node] : [];
|
|
930
|
+
}, driver.mode);
|
|
931
|
+
return this.selection;
|
|
932
|
+
}
|
|
933
|
+
/** Merge props into the current render while preserving component state. */
|
|
934
|
+
rerender(overrides) {
|
|
935
|
+
const driver = this.initialize();
|
|
936
|
+
this.props = { ...this.props, ...overrides };
|
|
937
|
+
driver.render(this.props, this.wrappers);
|
|
938
|
+
}
|
|
939
|
+
/** Flush already scheduled synchronous work; use {@link act} for asynchronous work. */
|
|
940
|
+
flush() {
|
|
941
|
+
this.initialize().flush();
|
|
942
|
+
}
|
|
943
|
+
/** Await React work scheduled by the callback. Await the component request or timer inside the callback. */
|
|
944
|
+
async act(callback) {
|
|
945
|
+
await this.initialize().act(callback);
|
|
946
|
+
}
|
|
947
|
+
/** Unmount the render. Calling this more than once is safe. */
|
|
948
|
+
unmount() {
|
|
949
|
+
if (this.disposed) return;
|
|
950
|
+
this.disposed = true;
|
|
951
|
+
mounted.delete(this);
|
|
952
|
+
this.driver?.unmount();
|
|
953
|
+
}
|
|
954
|
+
initialize() {
|
|
955
|
+
if (this.disposed)
|
|
956
|
+
throw new Error("Cannot use an unmounted render session");
|
|
957
|
+
if (!this.driver) {
|
|
958
|
+
this.driver = this.factory({
|
|
959
|
+
component: this.component,
|
|
960
|
+
props: this.props,
|
|
961
|
+
wrappers: this.wrappers,
|
|
962
|
+
initialElement: this.initialElement
|
|
963
|
+
});
|
|
964
|
+
mounted.add(this);
|
|
965
|
+
}
|
|
966
|
+
return this.driver;
|
|
967
|
+
}
|
|
968
|
+
};
|
|
969
|
+
function getComponentRenderer(component, defaultProps) {
|
|
970
|
+
const defaults = { ...defaultProps };
|
|
971
|
+
let defaultElement;
|
|
972
|
+
return {
|
|
973
|
+
shallow(overrides) {
|
|
974
|
+
return new RenderSession(
|
|
975
|
+
component,
|
|
976
|
+
overrides === void 0 ? defaults : { ...defaults, ...overrides },
|
|
977
|
+
createShallowDriver
|
|
978
|
+
);
|
|
979
|
+
},
|
|
980
|
+
mount(overrides) {
|
|
981
|
+
const props = overrides === void 0 ? defaults : { ...defaults, ...overrides };
|
|
982
|
+
const element = overrides === void 0 ? defaultElement ??= (0, import_react2.createElement)(component, defaults) : (0, import_react2.createElement)(component, props);
|
|
983
|
+
return new RenderSession(component, props, createMountDriver, element);
|
|
984
|
+
}
|
|
985
|
+
};
|
|
986
|
+
}
|
|
987
|
+
function cleanup() {
|
|
988
|
+
const errors = [];
|
|
989
|
+
for (const session of mounted) {
|
|
990
|
+
try {
|
|
991
|
+
session.unmount();
|
|
992
|
+
} catch (error) {
|
|
993
|
+
errors.push(error);
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
if (errors.length === 1) throw errors[0];
|
|
997
|
+
if (errors.length > 1)
|
|
998
|
+
throw new AggregateError(
|
|
999
|
+
errors,
|
|
1000
|
+
"Multiple render sessions failed to clean up"
|
|
1001
|
+
);
|
|
1002
|
+
}
|
|
1003
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1004
|
+
0 && (module.exports = {
|
|
1005
|
+
RenderSession,
|
|
1006
|
+
Subject,
|
|
1007
|
+
cleanup,
|
|
1008
|
+
getComponentRenderer
|
|
1009
|
+
});
|
|
1010
|
+
//# sourceMappingURL=index.cjs.map
|