@reckona/mreact-compat 0.0.169 → 0.0.171
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/dom-children.d.ts.map +1 -1
- package/dist/dom-children.js +53 -0
- package/dist/dom-children.js.map +1 -1
- package/dist/element.d.ts.map +1 -1
- package/dist/element.js +54 -18
- package/dist/element.js.map +1 -1
- package/dist/hooks.js +18 -11
- package/dist/hooks.js.map +1 -1
- package/dist/host-reconciler.d.ts.map +1 -1
- package/dist/host-reconciler.js +263 -31
- package/dist/host-reconciler.js.map +1 -1
- package/package.json +3 -3
- package/src/dom-children.ts +78 -0
- package/src/element.ts +84 -13
- package/src/hooks.ts +24 -11
- package/src/host-reconciler.ts +430 -42
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reckona/mreact-compat",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.171",
|
|
4
4
|
"description": "React-compatible runtime implementation for mreact.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"compatibility",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"access": "public"
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
|
-
"@reckona/mreact-reactive-core": "0.0.
|
|
73
|
-
"@reckona/mreact-shared": "0.0.
|
|
72
|
+
"@reckona/mreact-reactive-core": "0.0.171",
|
|
73
|
+
"@reckona/mreact-shared": "0.0.171"
|
|
74
74
|
}
|
|
75
75
|
}
|
package/src/dom-children.ts
CHANGED
|
@@ -45,6 +45,10 @@ export function syncScopedChildNodes(
|
|
|
45
45
|
after: ChildNode | null,
|
|
46
46
|
nextNodes: readonly Node[],
|
|
47
47
|
): void {
|
|
48
|
+
if (replaceEmptyFullChildList(parent, before, after, nextNodes)) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
48
52
|
if (replaceDisjointFullChildList(parent, before, after, nextNodes)) {
|
|
49
53
|
return;
|
|
50
54
|
}
|
|
@@ -57,6 +61,10 @@ export function syncScopedChildNodes(
|
|
|
57
61
|
return;
|
|
58
62
|
}
|
|
59
63
|
|
|
64
|
+
if (nextNodes.length > 16 && moveSingleSwappedPair(parent, before, after, nextNodes)) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
60
68
|
let cursor = parent.firstChild;
|
|
61
69
|
|
|
62
70
|
if (before !== null) {
|
|
@@ -91,6 +99,25 @@ export function syncScopedChildNodes(
|
|
|
91
99
|
}
|
|
92
100
|
}
|
|
93
101
|
|
|
102
|
+
function replaceEmptyFullChildList(
|
|
103
|
+
parent: ParentNode,
|
|
104
|
+
before: ChildNode | null,
|
|
105
|
+
after: ChildNode | null,
|
|
106
|
+
nextNodes: readonly Node[],
|
|
107
|
+
): boolean {
|
|
108
|
+
if (
|
|
109
|
+
before !== null ||
|
|
110
|
+
after !== null ||
|
|
111
|
+
nextNodes.length <= 16 ||
|
|
112
|
+
parent.childNodes.length !== 0
|
|
113
|
+
) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
parent.replaceChildren(...nextNodes);
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
|
|
94
121
|
function replaceDisjointFullChildList(
|
|
95
122
|
parent: ParentNode,
|
|
96
123
|
before: ChildNode | null,
|
|
@@ -177,6 +204,57 @@ function removeSingleMissingChild(
|
|
|
177
204
|
return true;
|
|
178
205
|
}
|
|
179
206
|
|
|
207
|
+
function moveSingleSwappedPair(
|
|
208
|
+
parent: ParentNode,
|
|
209
|
+
before: ChildNode | null,
|
|
210
|
+
after: ChildNode | null,
|
|
211
|
+
nextNodes: readonly Node[],
|
|
212
|
+
): boolean {
|
|
213
|
+
let cursor = before === null ? parent.firstChild : before.nextSibling;
|
|
214
|
+
let index = 0;
|
|
215
|
+
let firstMismatchIndex = -1;
|
|
216
|
+
let secondMismatchIndex = -1;
|
|
217
|
+
let firstCurrent: ChildNode | null = null;
|
|
218
|
+
let secondCurrent: ChildNode | null = null;
|
|
219
|
+
|
|
220
|
+
while (cursor !== null && cursor !== after && index < nextNodes.length) {
|
|
221
|
+
const current = cursor;
|
|
222
|
+
|
|
223
|
+
if (current !== nextNodes[index]) {
|
|
224
|
+
if (firstMismatchIndex === -1) {
|
|
225
|
+
firstMismatchIndex = index;
|
|
226
|
+
firstCurrent = current;
|
|
227
|
+
} else if (secondMismatchIndex === -1) {
|
|
228
|
+
secondMismatchIndex = index;
|
|
229
|
+
secondCurrent = current;
|
|
230
|
+
} else {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
cursor = current.nextSibling;
|
|
236
|
+
index += 1;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (
|
|
240
|
+
index !== nextNodes.length ||
|
|
241
|
+
cursor !== after ||
|
|
242
|
+
firstCurrent === null ||
|
|
243
|
+
secondCurrent === null ||
|
|
244
|
+
firstCurrent !== nextNodes[secondMismatchIndex] ||
|
|
245
|
+
secondCurrent !== nextNodes[firstMismatchIndex]
|
|
246
|
+
) {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
parent.insertBefore(secondCurrent, firstCurrent);
|
|
251
|
+
parent.insertBefore(
|
|
252
|
+
firstCurrent,
|
|
253
|
+
(nextNodes[secondMismatchIndex + 1] as ChildNode | undefined) ?? after,
|
|
254
|
+
);
|
|
255
|
+
return true;
|
|
256
|
+
}
|
|
257
|
+
|
|
180
258
|
export function removeChildIfPresent(parent: ParentNode, child: Node): void {
|
|
181
259
|
if (child.parentNode !== parent) {
|
|
182
260
|
return;
|
package/src/element.ts
CHANGED
|
@@ -100,17 +100,21 @@ export function createElement<P extends object>(
|
|
|
100
100
|
type: ElementType<P>,
|
|
101
101
|
config: (P & ReactReservedProps) | null,
|
|
102
102
|
...children: ReactCompatNode[]
|
|
103
|
+
): ReactCompatElement<P>;
|
|
104
|
+
export function createElement<P extends object>(
|
|
105
|
+
type: ElementType<P>,
|
|
106
|
+
config: (P & ReactReservedProps) | null,
|
|
103
107
|
): ReactCompatElement<P> {
|
|
108
|
+
const childCount = arguments.length - 2;
|
|
109
|
+
|
|
104
110
|
if (typeof type === "string") {
|
|
105
111
|
const key = config?.key === undefined ? null : String(config.key);
|
|
106
112
|
const ref = config?.ref ?? null;
|
|
107
|
-
const props =
|
|
113
|
+
const props = copyCreateElementProps(config) as P & {
|
|
114
|
+
children?: ReactCompatNode;
|
|
115
|
+
};
|
|
108
116
|
|
|
109
|
-
|
|
110
|
-
props.children = children[0];
|
|
111
|
-
} else if (children.length > 1) {
|
|
112
|
-
props.children = children;
|
|
113
|
-
}
|
|
117
|
+
assignCreateElementChildren(props, childCount, arguments);
|
|
114
118
|
|
|
115
119
|
setHostOwnPropsMeta(props);
|
|
116
120
|
|
|
@@ -127,15 +131,14 @@ export function createElement<P extends object>(
|
|
|
127
131
|
typeof type === "object" && type !== null ? normalizeElementType(type) : type;
|
|
128
132
|
const key = config?.key === undefined ? null : String(config.key);
|
|
129
133
|
const ref = config?.ref ?? null;
|
|
130
|
-
const props = applyDefaultProps(
|
|
134
|
+
const props = applyDefaultProps(
|
|
135
|
+
normalizedType,
|
|
136
|
+
copyCreateElementProps(config),
|
|
137
|
+
) as P & {
|
|
131
138
|
children?: ReactCompatNode;
|
|
132
139
|
};
|
|
133
140
|
|
|
134
|
-
|
|
135
|
-
props.children = children[0];
|
|
136
|
-
} else if (children.length > 1) {
|
|
137
|
-
props.children = children;
|
|
138
|
-
}
|
|
141
|
+
assignCreateElementChildren(props, childCount, arguments);
|
|
139
142
|
|
|
140
143
|
if (typeof normalizedType === "string") {
|
|
141
144
|
setHostOwnPropsMeta(props);
|
|
@@ -150,6 +153,30 @@ export function createElement<P extends object>(
|
|
|
150
153
|
};
|
|
151
154
|
}
|
|
152
155
|
|
|
156
|
+
function assignCreateElementChildren(
|
|
157
|
+
props: { children?: ReactCompatNode },
|
|
158
|
+
childCount: number,
|
|
159
|
+
args: IArguments,
|
|
160
|
+
): void {
|
|
161
|
+
if (childCount === 1) {
|
|
162
|
+
props.children = args[2] as ReactCompatNode;
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (childCount <= 1) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const children: ReactCompatNode[] = [];
|
|
171
|
+
children.length = childCount;
|
|
172
|
+
|
|
173
|
+
for (let index = 0; index < childCount; index += 1) {
|
|
174
|
+
children[index] = args[index + 2] as ReactCompatNode;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
props.children = children;
|
|
178
|
+
}
|
|
179
|
+
|
|
153
180
|
/** Creates a React-compatible element from JSX runtime arguments. */
|
|
154
181
|
export function createElementFromJsxConfig<P extends object>(
|
|
155
182
|
type: ElementType<P>,
|
|
@@ -312,6 +339,7 @@ function copyElementProps(
|
|
|
312
339
|
source: object | null | undefined,
|
|
313
340
|
base?: object,
|
|
314
341
|
omitChildren = false,
|
|
342
|
+
copySymbols: boolean | "internal" = true,
|
|
315
343
|
): Record<string, unknown> {
|
|
316
344
|
const props: Record<PropertyKey, unknown> = {};
|
|
317
345
|
|
|
@@ -324,7 +352,40 @@ function copyElementProps(
|
|
|
324
352
|
}
|
|
325
353
|
|
|
326
354
|
copyOwnStringElementProps(source, props, omitChildren);
|
|
327
|
-
|
|
355
|
+
if (copySymbols === "internal") {
|
|
356
|
+
copyInternalElementSymbolProps(source, props);
|
|
357
|
+
} else if (copySymbols) {
|
|
358
|
+
copyOwnSymbolElementProps(source, props);
|
|
359
|
+
}
|
|
360
|
+
return props as Record<string, unknown>;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
function copyCreateElementProps(
|
|
364
|
+
source: object | null | undefined,
|
|
365
|
+
): Record<string, unknown> {
|
|
366
|
+
const props: Record<PropertyKey, unknown> = {};
|
|
367
|
+
|
|
368
|
+
if (source === null || source === undefined) {
|
|
369
|
+
return props as Record<string, unknown>;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
const stringSource = source as Record<string, unknown>;
|
|
373
|
+
for (const name in source) {
|
|
374
|
+
if (!hasOwnProperty.call(source, name)) {
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (
|
|
379
|
+
name !== "key" &&
|
|
380
|
+
name !== "ref" &&
|
|
381
|
+
name !== "__self" &&
|
|
382
|
+
name !== "__source"
|
|
383
|
+
) {
|
|
384
|
+
props[name] = stringSource[name];
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
copyInternalElementSymbolProps(source, props);
|
|
328
389
|
return props as Record<string, unknown>;
|
|
329
390
|
}
|
|
330
391
|
|
|
@@ -361,6 +422,16 @@ function copyOwnSymbolElementProps(
|
|
|
361
422
|
}
|
|
362
423
|
}
|
|
363
424
|
|
|
425
|
+
function copyInternalElementSymbolProps(
|
|
426
|
+
source: object,
|
|
427
|
+
target: Record<PropertyKey, unknown>,
|
|
428
|
+
): void {
|
|
429
|
+
const symbolSource = source as Record<PropertyKey, unknown>;
|
|
430
|
+
if (hasOwnProperty.call(source, REACTIVE_TEXT_BINDING_META)) {
|
|
431
|
+
target[REACTIVE_TEXT_BINDING_META] = symbolSource[REACTIVE_TEXT_BINDING_META];
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
364
435
|
function normalizeElementType<P>(type: ElementType<P>): ElementType<P> {
|
|
365
436
|
return isReactCompatContextProviderShorthand(type) ? (type.Provider as ElementType<P>) : type;
|
|
366
437
|
}
|
package/src/hooks.ts
CHANGED
|
@@ -2214,6 +2214,10 @@ function cleanupInactiveInstances(runtime: RootRuntime): void {
|
|
|
2214
2214
|
return;
|
|
2215
2215
|
}
|
|
2216
2216
|
|
|
2217
|
+
if (activeInstanceKeys.size === runtime.instances.size) {
|
|
2218
|
+
return;
|
|
2219
|
+
}
|
|
2220
|
+
|
|
2217
2221
|
for (const [key, instance] of runtime.instances) {
|
|
2218
2222
|
if (!activeInstanceKeys.has(key)) {
|
|
2219
2223
|
cleanupInstance(instance);
|
|
@@ -2224,7 +2228,7 @@ function cleanupInactiveInstances(runtime: RootRuntime): void {
|
|
|
2224
2228
|
}
|
|
2225
2229
|
|
|
2226
2230
|
function indexInstanceKey(runtime: RootRuntime, key: string): void {
|
|
2227
|
-
|
|
2231
|
+
forEachInstanceKeyPrefix(key, (prefix) => {
|
|
2228
2232
|
let keys = runtime.instanceKeysByPrefix.get(prefix);
|
|
2229
2233
|
|
|
2230
2234
|
if (keys === undefined) {
|
|
@@ -2233,15 +2237,15 @@ function indexInstanceKey(runtime: RootRuntime, key: string): void {
|
|
|
2233
2237
|
}
|
|
2234
2238
|
|
|
2235
2239
|
keys.add(key);
|
|
2236
|
-
}
|
|
2240
|
+
});
|
|
2237
2241
|
}
|
|
2238
2242
|
|
|
2239
2243
|
function removeInstanceKeyFromIndex(runtime: RootRuntime, key: string): void {
|
|
2240
|
-
|
|
2244
|
+
forEachInstanceKeyPrefix(key, (prefix) => {
|
|
2241
2245
|
const keys = runtime.instanceKeysByPrefix.get(prefix);
|
|
2242
2246
|
|
|
2243
2247
|
if (keys === undefined) {
|
|
2244
|
-
|
|
2248
|
+
return;
|
|
2245
2249
|
}
|
|
2246
2250
|
|
|
2247
2251
|
keys.delete(key);
|
|
@@ -2249,18 +2253,27 @@ function removeInstanceKeyFromIndex(runtime: RootRuntime, key: string): void {
|
|
|
2249
2253
|
if (keys.size === 0) {
|
|
2250
2254
|
runtime.instanceKeysByPrefix.delete(prefix);
|
|
2251
2255
|
}
|
|
2252
|
-
}
|
|
2256
|
+
});
|
|
2253
2257
|
}
|
|
2254
2258
|
|
|
2255
|
-
function
|
|
2256
|
-
|
|
2257
|
-
|
|
2259
|
+
function forEachInstanceKeyPrefix(
|
|
2260
|
+
key: string,
|
|
2261
|
+
callback: (prefix: string) => void,
|
|
2262
|
+
): void {
|
|
2263
|
+
let start = 0;
|
|
2264
|
+
|
|
2265
|
+
while (start < key.length) {
|
|
2266
|
+
const next = key.indexOf(".", start);
|
|
2267
|
+
|
|
2268
|
+
if (next === -1) {
|
|
2269
|
+
break;
|
|
2270
|
+
}
|
|
2258
2271
|
|
|
2259
|
-
|
|
2260
|
-
|
|
2272
|
+
callback(key.slice(0, next));
|
|
2273
|
+
start = next + 1;
|
|
2261
2274
|
}
|
|
2262
2275
|
|
|
2263
|
-
|
|
2276
|
+
callback(key);
|
|
2264
2277
|
}
|
|
2265
2278
|
|
|
2266
2279
|
function cleanupInstance(instance: ComponentInstance): void {
|