foldkit 0.168.0 → 0.169.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/dom/inert.d.ts +7 -3
- package/dist/dom/inert.d.ts.map +1 -1
- package/dist/dom/inert.js +19 -9
- package/dist/dom/streamFromKeyBindings.d.ts +5 -3
- package/dist/dom/streamFromKeyBindings.d.ts.map +1 -1
- package/dist/dom/streamFromKeyBindings.js +7 -4
- package/dist/experimental/server/fragment.d.ts +15 -0
- package/dist/experimental/server/fragment.d.ts.map +1 -0
- package/dist/experimental/server/fragment.js +14 -0
- package/dist/experimental/server/server.d.ts +3 -2
- package/dist/experimental/server/server.d.ts.map +1 -1
- package/dist/experimental/server/server.js +20 -23
- package/dist/experimental/server/template.d.ts.map +1 -1
- package/dist/experimental/server/template.js +20 -19
- package/dist/html/boundary.d.ts +17 -16
- package/dist/html/boundary.d.ts.map +1 -1
- package/dist/html/boundary.js +9 -9
- package/dist/html/childAttribute.d.ts +5 -5
- package/dist/html/index.d.ts.map +1 -1
- package/dist/html/index.js +24 -17
- package/dist/html/lazy.d.ts +130 -0
- package/dist/html/lazy.d.ts.map +1 -1
- package/dist/html/lazy.js +54 -6
- package/dist/html/runtimeSingleton.d.ts +2 -2
- package/dist/html/runtimeSingleton.d.ts.map +1 -1
- package/dist/html/runtimeSingleton.js +2 -2
- package/dist/html/submodel.d.ts.map +1 -1
- package/dist/html/submodel.js +20 -11
- package/dist/imeComposition.d.ts +3 -0
- package/dist/imeComposition.d.ts.map +1 -0
- package/dist/imeComposition.js +6 -0
- package/dist/mount/index.d.ts +6 -5
- package/dist/mount/index.d.ts.map +1 -1
- package/dist/route/transition.d.ts +50 -0
- package/dist/route/transition.d.ts.map +1 -1
- package/dist/route/transition.js +48 -0
- package/dist/runtime/messageQueue.d.ts +1 -0
- package/dist/runtime/messageQueue.d.ts.map +1 -1
- package/dist/runtime/messageQueue.js +2 -0
- package/dist/runtime/renderer.d.ts.map +1 -1
- package/dist/runtime/renderer.js +18 -3
- package/dist/snabbdom/hooks.d.ts +2 -0
- package/dist/snabbdom/hooks.d.ts.map +1 -1
- package/dist/snabbdom/init.d.ts.map +1 -1
- package/dist/snabbdom/init.js +42 -12
- package/dist/test/internal.d.ts.map +1 -1
- package/dist/test/internal.js +9 -2
- package/dist/test/lazy.d.ts +26 -0
- package/dist/test/lazy.d.ts.map +1 -0
- package/dist/test/lazy.js +103 -0
- package/dist/test/public.d.ts +1 -0
- package/dist/test/public.d.ts.map +1 -1
- package/dist/test/public.js +1 -0
- package/package.json +1 -1
package/dist/dom/inert.d.ts
CHANGED
|
@@ -10,9 +10,13 @@ export declare const isolateOutsideElements: (allowedElements: ReadonlyArray<HTM
|
|
|
10
10
|
/**
|
|
11
11
|
* Marks all DOM elements outside the given selectors as `inert` and
|
|
12
12
|
* `aria-hidden="true"`. Walks each allowed element up to `document.body`,
|
|
13
|
-
* marking siblings that don't contain an allowed element.
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* marking siblings that don't contain an allowed element. Reference counting
|
|
14
|
+
* allows nested calls with different ids.
|
|
15
|
+
*
|
|
16
|
+
* Reusing an id acquires the replacement isolation before releasing the
|
|
17
|
+
* previous one, so shared elements keep `inert` and `aria-hidden` throughout.
|
|
18
|
+
* One `restoreInert` releases that id's isolation. Calling it before the
|
|
19
|
+
* pending render commits discards the request.
|
|
16
20
|
*
|
|
17
21
|
* @example
|
|
18
22
|
* ```typescript
|
package/dist/dom/inert.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inert.d.ts","sourceRoot":"","sources":["../../src/dom/inert.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAA2C,MAAM,QAAQ,CAAA;AAc/E,KAAK,cAAc,GAAG,aAAa,GAAG,OAAO,CAAA;AAoH7C,eAAO,MAAM,oBAAoB,QAAO,QAAQ,CAAC;IAC/C,MAAM,EAAE,CAAC,eAAe,EAAE,aAAa,CAAC,WAAW,CAAC,KAAK,IAAI,CAAA;IAC7D,QAAQ,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAA;IAC3C,uBAAuB,EAAE,CACvB,OAAO,EAAE,WAAW,EACpB,aAAa,EAAE,cAAc,KAC1B,IAAI,CAAA;IACT,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,CAyCA,CAAA;AAED,eAAO,MAAM,sBAAsB,oBAChB,aAAa,CAAC,WAAW,CAAC,KAC1C,CAAC,MAAM,IAAI,CAKb,CAAA;
|
|
1
|
+
{"version":3,"file":"inert.d.ts","sourceRoot":"","sources":["../../src/dom/inert.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAA2C,MAAM,QAAQ,CAAA;AAc/E,KAAK,cAAc,GAAG,aAAa,GAAG,OAAO,CAAA;AAoH7C,eAAO,MAAM,oBAAoB,QAAO,QAAQ,CAAC;IAC/C,MAAM,EAAE,CAAC,eAAe,EAAE,aAAa,CAAC,WAAW,CAAC,KAAK,IAAI,CAAA;IAC7D,QAAQ,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAA;IAC3C,uBAAuB,EAAE,CACvB,OAAO,EAAE,WAAW,EACpB,aAAa,EAAE,cAAc,KAC1B,IAAI,CAAA;IACT,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,CAyCA,CAAA;AAED,eAAO,MAAM,sBAAsB,oBAChB,aAAa,CAAC,WAAW,CAAC,KAC1C,CAAC,MAAM,IAAI,CAKb,CAAA;AAaD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,WAAW,OAClB,MAAM,oBACQ,aAAa,CAAC,MAAM,CAAC,KACtC,MAAM,CAAC,MAAM,CAAC,IAAI,CAmBjB,CAAA;AAEJ;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,OAAQ,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAIxD,CAAA"}
|
package/dist/dom/inert.js
CHANGED
|
@@ -123,12 +123,24 @@ export const isolateOutsideElements = (allowedElements) => {
|
|
|
123
123
|
isolation.update(allowedElements);
|
|
124
124
|
return isolation.dispose;
|
|
125
125
|
};
|
|
126
|
+
const releaseStoredCleanups = (id) => {
|
|
127
|
+
const cleanupFunctions = inertState.cleanups.get(id);
|
|
128
|
+
if (cleanupFunctions === undefined) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
inertState.cleanups.delete(id);
|
|
132
|
+
Array.forEach(cleanupFunctions, cleanup => cleanup());
|
|
133
|
+
};
|
|
126
134
|
/**
|
|
127
135
|
* Marks all DOM elements outside the given selectors as `inert` and
|
|
128
136
|
* `aria-hidden="true"`. Walks each allowed element up to `document.body`,
|
|
129
|
-
* marking siblings that don't contain an allowed element.
|
|
130
|
-
*
|
|
131
|
-
*
|
|
137
|
+
* marking siblings that don't contain an allowed element. Reference counting
|
|
138
|
+
* allows nested calls with different ids.
|
|
139
|
+
*
|
|
140
|
+
* Reusing an id acquires the replacement isolation before releasing the
|
|
141
|
+
* previous one, so shared elements keep `inert` and `aria-hidden` throughout.
|
|
142
|
+
* One `restoreInert` releases that id's isolation. Calling it before the
|
|
143
|
+
* pending render commits discards the request.
|
|
132
144
|
*
|
|
133
145
|
* @example
|
|
134
146
|
* ```typescript
|
|
@@ -146,7 +158,9 @@ export const inertOthers = (id, allowedSelectors) => Effect.gen(function* () {
|
|
|
146
158
|
return;
|
|
147
159
|
}
|
|
148
160
|
const allowedElements = resolveElements(allowedSelectors);
|
|
149
|
-
|
|
161
|
+
const dispose = isolateOutsideElements(allowedElements);
|
|
162
|
+
releaseStoredCleanups(id);
|
|
163
|
+
inertState.cleanups.set(id, [dispose]);
|
|
150
164
|
});
|
|
151
165
|
/**
|
|
152
166
|
* Restores all elements previously marked inert by `inertOthers` for the
|
|
@@ -160,9 +174,5 @@ export const inertOthers = (id, allowedSelectors) => Effect.gen(function* () {
|
|
|
160
174
|
*/
|
|
161
175
|
export const restoreInert = (id) => Effect.sync(() => {
|
|
162
176
|
inertState.requests.delete(id);
|
|
163
|
-
|
|
164
|
-
if (cleanupFunctions) {
|
|
165
|
-
Array.forEach(cleanupFunctions, cleanup => cleanup());
|
|
166
|
-
inertState.cleanups.delete(id);
|
|
167
|
-
}
|
|
177
|
+
releaseStoredCleanups(id);
|
|
168
178
|
});
|
|
@@ -52,9 +52,11 @@ export type StreamFromKeyBindingsConfig<Output> = Readonly<{
|
|
|
52
52
|
* Bindings are suppressed by default when the event's composed path contains
|
|
53
53
|
* an `input`, `textarea`, `select`, or contenteditable element. Set
|
|
54
54
|
* `whileTyping` to `'Allow'` for a binding that must work there. Events emitted
|
|
55
|
-
* during IME composition are always ignored
|
|
56
|
-
*
|
|
57
|
-
*
|
|
55
|
+
* during IME composition are always ignored, including a keydown some browsers
|
|
56
|
+
* report with `keyCode` 229 and `isComposing` false. Repeated keydowns are
|
|
57
|
+
* ignored for one-press bindings unless `whenRepeated` is `'Allow'`. An event
|
|
58
|
+
* another handler already canceled is ignored and clears any sequence in
|
|
59
|
+
* progress.
|
|
58
60
|
*
|
|
59
61
|
* Matched key presses call `preventDefault()` before dispatching. For a
|
|
60
62
|
* sequence, that policy applies to every matched press. Set `preventDefault`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streamFromKeyBindings.d.ts","sourceRoot":"","sources":["../../src/dom/streamFromKeyBindings.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EAOR,MAAM,EAGP,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"streamFromKeyBindings.d.ts","sourceRoot":"","sources":["../../src/dom/streamFromKeyBindings.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EAOR,MAAM,EAGP,MAAM,QAAQ,CAAA;AAIf,oFAAoF;AACpF,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,OAAO,CAAA;AAE9C,mEAAmE;AACnE,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,QAAQ,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;AAE/E,KAAK,WAAW,CAAC,MAAM,IAAI,QAAQ,CAAC;IAClC,IAAI,EAAE,WAAW,CAAA;IACjB,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,MAAM,CAAA;IAC1C,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB,CAAC,CAAA;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,CAAC,MAAM,IAAI,WAAW,CAAC,MAAM,CAAC,GAClD,CACI,QAAQ,CAAC;IACP,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAA;CAClC,CAAC,GACF,QAAQ,CAAC;IACP,IAAI,EAAE,QAAQ,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IAClD,YAAY,CAAC,EAAE,KAAK,CAAA;CACrB,CAAC,CACL,CAAA;AAEH,KAAK,MAAM,GAAG,SAAS,GAAG,MAAM,CAAA;AAEhC,yEAAyE;AACzE,MAAM,MAAM,2BAA2B,CAAC,MAAM,IAAI,QAAQ,CAAC;IACzD,QAAQ,EAAE,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAA;IAC3C,MAAM,CAAC,EAAE,WAAW,GAAG,CAAC,MAAM,WAAW,CAAC,CAAA;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,eAAe,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAA;CACjC,CAAC,CAAA;AAwzBF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4EG;AACH,eAAO,MAAM,qBAAqB,GAAI,MAAM,UAClC,2BAA2B,CAAC,MAAM,CAAC,KAC1C,MAAM,CAAC,MAAM,CAAC,MAAM,CACuC,CAAA"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Array, Duration, Effect, Match, Number, Option, Predicate, Queue, Stream, String, pipe, } from 'effect';
|
|
2
|
+
import { isImeCompositionKeydown } from '../imeComposition.js';
|
|
2
3
|
const DEFAULT_SEQUENCE_TIMEOUT = Duration.seconds(1);
|
|
3
4
|
const APPLE_PLATFORM_PATTERN = /Mac|iPhone|iPad|iPod/;
|
|
4
5
|
const MODIFIER_KEYS = [
|
|
@@ -312,7 +313,7 @@ const handleKeyBindingEvent = (context, event) => {
|
|
|
312
313
|
if (!isKeyboardEvent(event)) {
|
|
313
314
|
return;
|
|
314
315
|
}
|
|
315
|
-
if (event.defaultPrevented || event
|
|
316
|
+
if (event.defaultPrevented || isImeCompositionKeydown(event)) {
|
|
316
317
|
context.sequenceController.clearSequence();
|
|
317
318
|
return;
|
|
318
319
|
}
|
|
@@ -432,9 +433,11 @@ const keyBindingStream = (config) => Stream.callback(queue => {
|
|
|
432
433
|
* Bindings are suppressed by default when the event's composed path contains
|
|
433
434
|
* an `input`, `textarea`, `select`, or contenteditable element. Set
|
|
434
435
|
* `whileTyping` to `'Allow'` for a binding that must work there. Events emitted
|
|
435
|
-
* during IME composition are always ignored
|
|
436
|
-
*
|
|
437
|
-
*
|
|
436
|
+
* during IME composition are always ignored, including a keydown some browsers
|
|
437
|
+
* report with `keyCode` 229 and `isComposing` false. Repeated keydowns are
|
|
438
|
+
* ignored for one-press bindings unless `whenRepeated` is `'Allow'`. An event
|
|
439
|
+
* another handler already canceled is ignored and clears any sequence in
|
|
440
|
+
* progress.
|
|
438
441
|
*
|
|
439
442
|
* Matched key presses call `preventDefault()` before dispatching. For a
|
|
440
443
|
* sequence, that policy applies to every matched press. Set `preventDefault`
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { DefaultTreeAdapterMap } from 'parse5';
|
|
2
|
+
/** The same rendered fragment parsed with scripting enabled and disabled.
|
|
3
|
+
* @internal
|
|
4
|
+
*/
|
|
5
|
+
export type ParsedFragmentModes = Readonly<{
|
|
6
|
+
scripted: DefaultTreeAdapterMap['documentFragment'];
|
|
7
|
+
unscripted: DefaultTreeAdapterMap['documentFragment'];
|
|
8
|
+
}>;
|
|
9
|
+
/** Parses both scripting modes in the supplied HTML insertion context.
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
export declare const parseFragmentModes: (context: DefaultTreeAdapterMap['element'], html: string, options?: Readonly<{
|
|
13
|
+
sourceCodeLocationInfo?: boolean;
|
|
14
|
+
}>) => ParsedFragmentModes;
|
|
15
|
+
//# sourceMappingURL=fragment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fragment.d.ts","sourceRoot":"","sources":["../../../src/experimental/server/fragment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,QAAQ,CAAA;AAGnD;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,QAAQ,EAAE,qBAAqB,CAAC,kBAAkB,CAAC,CAAA;IACnD,UAAU,EAAE,qBAAqB,CAAC,kBAAkB,CAAC,CAAA;CACtD,CAAC,CAAA;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,YACpB,qBAAqB,CAAC,SAAS,CAAC,QACnC,MAAM,YACH,QAAQ,CAAC;IAAE,sBAAsB,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,KACtD,mBASD,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { parseFragment } from 'parse5';
|
|
2
|
+
/** Parses both scripting modes in the supplied HTML insertion context.
|
|
3
|
+
* @internal
|
|
4
|
+
*/
|
|
5
|
+
export const parseFragmentModes = (context, html, options = {}) => ({
|
|
6
|
+
scripted: parseFragment(context, html, {
|
|
7
|
+
...options,
|
|
8
|
+
scriptingEnabled: true,
|
|
9
|
+
}),
|
|
10
|
+
unscripted: parseFragment(context, html, {
|
|
11
|
+
...options,
|
|
12
|
+
scriptingEnabled: false,
|
|
13
|
+
}),
|
|
14
|
+
});
|
|
@@ -3,8 +3,9 @@ import { type Document, type HtmlBuilder } from '../../html/index.js';
|
|
|
3
3
|
import { FOLDKIT_APP_ATTRIBUTE, FOLDKIT_FLAGS_ATTRIBUTE } from '../../hydrationMarker.js';
|
|
4
4
|
import type { Return as UpdateReturn } from '../../update/index.js';
|
|
5
5
|
import { Url } from '../../url/index.js';
|
|
6
|
-
|
|
7
|
-
export declare const
|
|
6
|
+
import { type ParsedFragmentModes } from './fragment.js';
|
|
7
|
+
export declare const __assertNoDeclarativeShadowRoot: (fragments: ParsedFragmentModes) => void;
|
|
8
|
+
export declare const __assertNoLiveBaseElement: (fragments: ParsedFragmentModes) => void;
|
|
8
9
|
export declare const __assertNoDocumentStructureEscape: (html: string) => void;
|
|
9
10
|
export { FOLDKIT_APP_ATTRIBUTE, FOLDKIT_FLAGS_ATTRIBUTE };
|
|
10
11
|
/** The server render of one request: the body markup and the `Document` head
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/experimental/server/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,MAAM,EAGN,MAAM,EAGP,MAAM,QAAQ,CAAA;AAmBf,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,WAAW,EAGjB,MAAM,qBAAqB,CAAA;AAM5B,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACxB,MAAM,0BAA0B,CAAA;AAQjC,OAAO,KAAK,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACnE,OAAO,EAAE,GAAG,EAAc,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/experimental/server/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,6 +10,7 @@ import { HYDRATION_IDENTITY_ATTRIBUTE, HYDRATION_KEY_ATTRIBUTE, } from '../../hy
|
|
|
10
10
|
import { hasTrustedInnerHtml } from '../../propertyProvenance.js';
|
|
11
11
|
import { tagNameFromSelector } from '../../tagName.js';
|
|
12
12
|
import { fromString } from '../../url/index.js';
|
|
13
|
+
import { parseFragmentModes } from './fragment.js';
|
|
13
14
|
import { controlledValueContent, escapeAttributeValue, serializeHtml, } from './serialize.js';
|
|
14
15
|
const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
|
|
15
16
|
const isParse5Element = (node) => 'tagName' in node;
|
|
@@ -352,14 +353,8 @@ const assertInnerHtmlContextMatches = (parsed, vnode) => {
|
|
|
352
353
|
'tree. Move the fragment outside that context or build the content with ' +
|
|
353
354
|
'ordinary view children.');
|
|
354
355
|
};
|
|
355
|
-
const assertNoscriptModesAgree = (
|
|
356
|
-
|
|
357
|
-
scriptingEnabled: true,
|
|
358
|
-
});
|
|
359
|
-
const unscripted = parseFragment(DIV_FRAGMENT_CONTEXT, html, {
|
|
360
|
-
scriptingEnabled: false,
|
|
361
|
-
});
|
|
362
|
-
if (parsedChildrenAgree(scripted, unscripted)) {
|
|
356
|
+
const assertNoscriptModesAgree = (fragments) => {
|
|
357
|
+
if (parsedChildrenAgree(fragments.scripted, fragments.unscripted)) {
|
|
363
358
|
return;
|
|
364
359
|
}
|
|
365
360
|
throw new Error('[foldkit] <noscript> content changes the rest of the page when a browser ' +
|
|
@@ -397,8 +392,9 @@ const declaresShadowRoot = (element) => element.tagName.toLowerCase() === 'templ
|
|
|
397
392
|
const hasDeclarativeShadowRoot = (node) => node.childNodes.some(child => isParse5Element(child) &&
|
|
398
393
|
(declaresShadowRoot(child) ||
|
|
399
394
|
hasDeclarativeShadowRoot(traversableContent(child))));
|
|
400
|
-
export const __assertNoDeclarativeShadowRoot = (
|
|
401
|
-
const declaresInEitherMode =
|
|
395
|
+
export const __assertNoDeclarativeShadowRoot = (fragments) => {
|
|
396
|
+
const declaresInEitherMode = hasDeclarativeShadowRoot(fragments.scripted) ||
|
|
397
|
+
hasDeclarativeShadowRoot(fragments.unscripted);
|
|
402
398
|
if (!declaresInEitherMode) {
|
|
403
399
|
return;
|
|
404
400
|
}
|
|
@@ -432,8 +428,9 @@ const hasLiveBaseElement = (node) => {
|
|
|
432
428
|
}
|
|
433
429
|
return false;
|
|
434
430
|
};
|
|
435
|
-
export const __assertNoLiveBaseElement = (
|
|
436
|
-
const hasBaseInEitherMode =
|
|
431
|
+
export const __assertNoLiveBaseElement = (fragments) => {
|
|
432
|
+
const hasBaseInEitherMode = hasLiveBaseElement(fragments.scripted) ||
|
|
433
|
+
hasLiveBaseElement(fragments.unscripted);
|
|
437
434
|
if (!hasBaseInEitherMode) {
|
|
438
435
|
return;
|
|
439
436
|
}
|
|
@@ -643,8 +640,7 @@ const assertNoReservedHandoffMarkers = (root) => {
|
|
|
643
640
|
// invariant that the served root parses back to the single intended element.
|
|
644
641
|
// The single element the served markup parses back to, or a refusal naming what
|
|
645
642
|
// the parser did to it instead.
|
|
646
|
-
const parsedRootOf = (
|
|
647
|
-
const fragment = parseFragment(DIV_FRAGMENT_CONTEXT, html, {});
|
|
643
|
+
const parsedRootOf = (fragment, root) => {
|
|
648
644
|
const significant = fragment.childNodes.filter(node => !isIgnorableText(node));
|
|
649
645
|
const only = significant[0];
|
|
650
646
|
if (significant.length !== 1 ||
|
|
@@ -681,13 +677,13 @@ const parsedRootOf = (html, root) => {
|
|
|
681
677
|
// reshaped subtree, so without it a dropped subtree is simply lost, with nothing
|
|
682
678
|
// left to notice. What stays conditional is the marker check below: only a
|
|
683
679
|
// hydratable render emits a stamp for the parser to move.
|
|
684
|
-
const assertParsedRootMatchesView = (
|
|
685
|
-
const parsed = parsedRootOf(
|
|
680
|
+
const assertParsedRootMatchesView = (fragment, root) => {
|
|
681
|
+
const parsed = parsedRootOf(fragment, root);
|
|
686
682
|
assertNoReservedHandoffMarkers(parsed);
|
|
687
683
|
assertStructureMatches(parsed, root);
|
|
688
684
|
};
|
|
689
|
-
const assertSingleStampedRoot = (
|
|
690
|
-
const only = parsedRootOf(
|
|
685
|
+
const assertSingleStampedRoot = (fragment, runtimeId, buildId, root) => {
|
|
686
|
+
const only = parsedRootOf(fragment, root);
|
|
691
687
|
const applicationMarkers = elementsCarrying(only, FOLDKIT_APP_ATTRIBUTE);
|
|
692
688
|
const buildMarkers = elementsCarrying(only, HYDRATION_BUILD_ATTRIBUTE);
|
|
693
689
|
const flagsMarkers = elementsCarrying(only, FOLDKIT_FLAGS_ATTRIBUTE);
|
|
@@ -895,16 +891,17 @@ export function renderToString(config, options) {
|
|
|
895
891
|
// is placed into a document the same way, so a root that does not close
|
|
896
892
|
// cleanly swallows whatever the host writes after it either way.
|
|
897
893
|
assertRootClosesCleanly(html);
|
|
898
|
-
|
|
899
|
-
|
|
894
|
+
const fragments = parseFragmentModes(DIV_FRAGMENT_CONTEXT, html);
|
|
895
|
+
assertNoscriptModesAgree(fragments);
|
|
896
|
+
__assertNoDeclarativeShadowRoot(fragments);
|
|
900
897
|
__assertNoDocumentStructureEscape(html);
|
|
901
|
-
__assertNoLiveBaseElement(
|
|
898
|
+
__assertNoLiveBaseElement(fragments);
|
|
902
899
|
if (nextDocument.body !== null) {
|
|
903
900
|
if (isHydratable) {
|
|
904
|
-
assertSingleStampedRoot(
|
|
901
|
+
assertSingleStampedRoot(fragments.scripted, runtimeId, buildId, nextDocument.body);
|
|
905
902
|
}
|
|
906
903
|
else {
|
|
907
|
-
assertParsedRootMatchesView(
|
|
904
|
+
assertParsedRootMatchesView(fragments.scripted, nextDocument.body);
|
|
908
905
|
}
|
|
909
906
|
}
|
|
910
907
|
return html;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../../src/experimental/server/template.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../../src/experimental/server/template.ts"],"names":[],"mappings":"AAUA,OAAO,EACL,KAAK,mBAAmB,EAIzB,MAAM,aAAa,CAAA;AAyoBpB;;;GAGG;AACH,MAAM,MAAM,yBAAyB,GAAG,QAAQ,CAAC;IAC/C;iDAC6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAC,CAAA;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,eAAO,MAAM,kBAAkB,aACnB,MAAM,YACN,mBAAmB,YACnB,yBAAyB,KAClC,MAkOF,CAAA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { html as Parse5Html, defaultTreeAdapter, parse
|
|
1
|
+
import { html as Parse5Html, defaultTreeAdapter, parse } from 'parse5';
|
|
2
2
|
import { HYDRATION_BUILD_ATTRIBUTE } from '../../buildToken.js';
|
|
3
3
|
import { FOLDKIT_APP_ATTRIBUTE, FOLDKIT_FLAGS_ATTRIBUTE, } from '../../hydrationMarker.js';
|
|
4
|
+
import { parseFragmentModes } from './fragment.js';
|
|
4
5
|
import { escapeAttributeValue, escapeText } from './serialize.js';
|
|
5
6
|
import { __assertNoDeclarativeShadowRoot, __assertNoDocumentStructureEscape, __assertNoLiveBaseElement, } from './server.js';
|
|
6
7
|
const DEFAULT_CONTAINER_ID = 'root';
|
|
@@ -236,10 +237,7 @@ const shapesAround = (parent, child) => {
|
|
|
236
237
|
}
|
|
237
238
|
return { shapes, index };
|
|
238
239
|
};
|
|
239
|
-
const assertInjectionIsFaithful = (page,
|
|
240
|
-
const parsedTemplate = parse(template, {
|
|
241
|
-
scriptingEnabled: isScriptingEnabled,
|
|
242
|
-
});
|
|
240
|
+
const assertInjectionIsFaithful = (page, parsedTemplate, renderedHtml, containerId, isScriptingEnabled) => {
|
|
243
241
|
const container = firstMatching(parsedTemplate, element => isContainerPlaceholder(element, containerId));
|
|
244
242
|
const containerParent = container === undefined ? undefined : parentOf(container);
|
|
245
243
|
if (container === undefined || containerParent === undefined) {
|
|
@@ -362,11 +360,7 @@ const assertRenderedSourceIsPreserved = (renderedHtml, parsed) => {
|
|
|
362
360
|
};
|
|
363
361
|
// The runtime id the rendered markup stamps on its root, or `undefined` when it
|
|
364
362
|
// carries no stamp (a render that nothing will hydrate).
|
|
365
|
-
const runtimeIdInMode = (renderedHtml,
|
|
366
|
-
const parsed = parseFragment(RENDERED_FRAGMENT_CONTEXT, renderedHtml, {
|
|
367
|
-
scriptingEnabled: isScriptingEnabled,
|
|
368
|
-
sourceCodeLocationInfo: true,
|
|
369
|
-
});
|
|
363
|
+
const runtimeIdInMode = (renderedHtml, parsed) => {
|
|
370
364
|
assertRenderedSourceIsPreserved(renderedHtml, parsed);
|
|
371
365
|
const applicationMarkers = collectMatchingIncludingTemplateContent(parsed, element => attributeValue(element, FOLDKIT_APP_ATTRIBUTE) !== undefined);
|
|
372
366
|
const flagsMarkers = collectMatchingIncludingTemplateContent(parsed, element => attributeValue(element, FOLDKIT_FLAGS_ATTRIBUTE) !== undefined);
|
|
@@ -420,9 +414,9 @@ const runtimeIdInMode = (renderedHtml, isScriptingEnabled) => {
|
|
|
420
414
|
}
|
|
421
415
|
return runtimeId;
|
|
422
416
|
};
|
|
423
|
-
const runtimeIdOf = (renderedHtml) => {
|
|
424
|
-
const enabled = runtimeIdInMode(renderedHtml,
|
|
425
|
-
const disabled = runtimeIdInMode(renderedHtml,
|
|
417
|
+
const runtimeIdOf = (renderedHtml, fragments) => {
|
|
418
|
+
const enabled = runtimeIdInMode(renderedHtml, fragments.scripted);
|
|
419
|
+
const disabled = runtimeIdInMode(renderedHtml, fragments.unscripted);
|
|
426
420
|
if (enabled !== disabled) {
|
|
427
421
|
throw new Error('[foldkit] injectIntoTemplate received rendered markup whose root and ' +
|
|
428
422
|
'Flags ownership changes when scripting is disabled.');
|
|
@@ -501,7 +495,11 @@ export const injectIntoTemplate = (template, rendered, options) => {
|
|
|
501
495
|
// Distinct ids are not a licence to hydrate two applications on one page.
|
|
502
496
|
// Each page-owning application rewrites the document's metadata and installs
|
|
503
497
|
// its own navigation listeners, which no id divides between them.
|
|
504
|
-
const
|
|
498
|
+
const { html: renderedHtml } = rendered;
|
|
499
|
+
const fragments = parseFragmentModes(RENDERED_FRAGMENT_CONTEXT, renderedHtml, {
|
|
500
|
+
sourceCodeLocationInfo: true,
|
|
501
|
+
});
|
|
502
|
+
const renderedRuntimeId = runtimeIdOf(renderedHtml, fragments);
|
|
505
503
|
if (renderedRuntimeId !== undefined) {
|
|
506
504
|
const existing = collectMatching(document, element => attributeValue(element, FOLDKIT_APP_ATTRIBUTE) === renderedRuntimeId);
|
|
507
505
|
if (existing.length > 0) {
|
|
@@ -551,15 +549,15 @@ export const injectIntoTemplate = (template, rendered, options) => {
|
|
|
551
549
|
const mutations = [];
|
|
552
550
|
const container = containers[0];
|
|
553
551
|
assertNeutralInsertionContext(container, containerId);
|
|
554
|
-
__assertNoDeclarativeShadowRoot(
|
|
555
|
-
__assertNoDocumentStructureEscape(
|
|
556
|
-
__assertNoLiveBaseElement(
|
|
552
|
+
__assertNoDeclarativeShadowRoot(fragments);
|
|
553
|
+
__assertNoDocumentStructureEscape(renderedHtml);
|
|
554
|
+
__assertNoLiveBaseElement(fragments);
|
|
557
555
|
const containerLocation = container.sourceCodeLocation;
|
|
558
556
|
if (containerLocation != null) {
|
|
559
557
|
mutations.push({
|
|
560
558
|
start: containerLocation.startOffset,
|
|
561
559
|
end: containerLocation.endOffset,
|
|
562
|
-
replacement:
|
|
560
|
+
replacement: renderedHtml,
|
|
563
561
|
});
|
|
564
562
|
}
|
|
565
563
|
const title = titles[0];
|
|
@@ -623,7 +621,10 @@ export const injectIntoTemplate = (template, rendered, options) => {
|
|
|
623
621
|
// document the same way, and markup the parser drops is lost with no
|
|
624
622
|
// hydration to rebuild it.
|
|
625
623
|
for (const isScriptingEnabled of [true, false]) {
|
|
626
|
-
|
|
624
|
+
const parsedTemplate = isScriptingEnabled
|
|
625
|
+
? document
|
|
626
|
+
: parse(template, { scriptingEnabled: false });
|
|
627
|
+
assertInjectionIsFaithful(page, parsedTemplate, renderedHtml, containerId, isScriptingEnabled);
|
|
627
628
|
}
|
|
628
629
|
return page;
|
|
629
630
|
};
|
package/dist/html/boundary.d.ts
CHANGED
|
@@ -37,9 +37,9 @@ export declare const composeBoundary: (parent: BoundaryId, childId: string) => B
|
|
|
37
37
|
/** Per-runtime registry of Submodel wrapping descriptors. The runtime
|
|
38
38
|
* creates one of these in `start` and reuses it across renders.
|
|
39
39
|
* `h.submodel` writes into `wraps` each render and attaches a snabbdom
|
|
40
|
-
* `
|
|
41
|
-
*
|
|
42
|
-
*
|
|
40
|
+
* `postdestroy` hook that calls `deregisterBoundaryWrap` when snabbdom
|
|
41
|
+
* destroys the corresponding vnode. The dispatch path reads from `wraps` at
|
|
42
|
+
* event-fire time.
|
|
43
43
|
*
|
|
44
44
|
* `boundaryDispatches` caches per-(outerDispatch, boundaryId) dispatcher
|
|
45
45
|
* closures so `requireDispatch` returns a stable reference across
|
|
@@ -56,8 +56,9 @@ export declare const composeBoundary: (parent: BoundaryId, childId: string) => B
|
|
|
56
56
|
* replay render's wraps occupy `wraps`. Its dispatcher therefore reads only
|
|
57
57
|
* the wraps registered by renders with the same root Mount dispatcher, while
|
|
58
58
|
* still seeing replacements from later live renders. `mountWrapOwners`
|
|
59
|
-
* records every owner that has occupied a boundary so its final
|
|
60
|
-
* can clear entries whose earlier hooks were replaced by
|
|
59
|
+
* records every owner that has occupied a boundary so its final
|
|
60
|
+
* `postdestroy` hook can clear entries whose earlier hooks were replaced by
|
|
61
|
+
* in-place patches.
|
|
61
62
|
*
|
|
62
63
|
* `seenThisRender` tracks boundaries marked alive during the current
|
|
63
64
|
* render for duplicate-slotId detection: two `h.submodel` calls
|
|
@@ -69,8 +70,8 @@ export declare const composeBoundary: (parent: BoundaryId, childId: string) => B
|
|
|
69
70
|
* cache hit are replayed into this map via
|
|
70
71
|
* {@link restoreBoundaryWrapsForLazyHit} so the duplicate-slotId guard
|
|
71
72
|
* catches collisions against memoized siblings, not just against siblings
|
|
72
|
-
* that re-ran this frame. It does not drive pruning; VNode
|
|
73
|
-
* remove a descriptor only when it is still the current entry, so an old
|
|
73
|
+
* that re-ran this frame. It does not drive pruning; VNode `postdestroy`
|
|
74
|
+
* hooks remove a descriptor only when it is still the current entry, so an old
|
|
74
75
|
* root cannot delete a same-cycle remount.
|
|
75
76
|
*
|
|
76
77
|
* `lazyTrackingStack` is a stack of maps used by `createLazy` and
|
|
@@ -88,7 +89,7 @@ export declare const composeBoundary: (parent: BoundaryId, childId: string) => B
|
|
|
88
89
|
* Submodel view's registration and lazy-cache writes transactional. If that
|
|
89
90
|
* view throws or returns `null`, every nested registration and cache entry it
|
|
90
91
|
* produced is restored because none of those VNodes will reach snabbdom and
|
|
91
|
-
* run its
|
|
92
|
+
* run its `postdestroy` hook. */
|
|
92
93
|
export type BoundaryRegistry = {
|
|
93
94
|
readonly wraps: Map<BoundaryId, WrapDescriptor>;
|
|
94
95
|
readonly boundaryDispatches: WeakMap<DispatchSync, Map<BoundaryId, DispatchSync>>;
|
|
@@ -124,8 +125,9 @@ export declare const endLazyTracking: (registry: BoundaryRegistry) => void;
|
|
|
124
125
|
export declare const restoreBoundaryWrapsForLazyHit: (registry: BoundaryRegistry, trackedBoundaries: ReadonlyMap<BoundaryId, TrackedBoundaryWrap>) => void;
|
|
125
126
|
/** Removes a boundary's wrap when it still matches the descriptor owned by the
|
|
126
127
|
* VNode being destroyed. A replacement registered earlier in the same patch
|
|
127
|
-
* is left intact. Called by `h.submodel`'s
|
|
128
|
-
* VNode
|
|
128
|
+
* is left intact. Called by `h.submodel`'s `postdestroy` hook when snabbdom
|
|
129
|
+
* destroys the corresponding VNode, after every `destroy` hook in that VNode's
|
|
130
|
+
* subtree has run.
|
|
129
131
|
*
|
|
130
132
|
* Does not touch `boundaryDispatches`: it is a WeakMap keyed by
|
|
131
133
|
* outerDispatch, so per-outerDispatch inner Maps become unreachable and
|
|
@@ -154,11 +156,10 @@ export declare const rollbackBoundaryWrapTransaction: (registry: BoundaryRegistr
|
|
|
154
156
|
* which defers the chain lookup to fire time, this snapshots the chain at call
|
|
155
157
|
* time so the resulting thunk survives the boundary being deregistered.
|
|
156
158
|
*
|
|
157
|
-
* Used by `OnUnmount
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
* avoids that race. Throws here (at resolve time, boundary alive) if a wrap is
|
|
159
|
+
* Used by `OnUnmount`, whose dispatch runs during teardown or, after a failed
|
|
160
|
+
* replay patch, later still. Resolving eagerly while the chain is live means
|
|
161
|
+
* that dispatch does not depend on what the registry holds at teardown time.
|
|
162
|
+
* Throws here (at resolve time, boundary alive) if a wrap is
|
|
162
163
|
* somehow already missing, surfacing a real corruption rather than misrouting. */
|
|
163
164
|
export declare const resolveBoundaryDispatchThunk: (registry: BoundaryRegistry, outerDispatch: DispatchSync, boundaryId: BoundaryId, message: unknown) => (() => void);
|
|
164
165
|
/** Collects the `toParentMessage` wrapping chain for `boundaryId`, innermost
|
|
@@ -181,7 +182,7 @@ export declare const resolveMountBoundaryDispatch: (registry: BoundaryRegistry,
|
|
|
181
182
|
* per-render duplicate-slotId tracking map so siblings inside the
|
|
182
183
|
* same parent boundary can be re-validated. Does not touch the wrap
|
|
183
184
|
* or dispatcher tables. Those persist across renders and are evicted
|
|
184
|
-
* by VNode
|
|
185
|
+
* by VNode `postdestroy` hooks instead. */
|
|
185
186
|
export declare const beginRender: (registry: BoundaryRegistry) => void;
|
|
186
187
|
export {};
|
|
187
188
|
//# sourceMappingURL=boundary.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boundary.d.ts","sourceRoot":"","sources":["../../src/html/boundary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAEzD,wDAAwD;AACxD,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,eAAe,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAA;CAC/C,CAAC,CAAA;AAEF;;;;eAIe;AACf,MAAM,MAAM,UAAU,GAAG,MAAM,CAAA;AAI/B,KAAK,wBAAwB,GAAG,QAAQ,CAAC;IACvC,IAAI,EAAE,cAAc,CAAA;IACpB,UAAU,EAAE,UAAU,CAAA;IACtB,UAAU,EAAE,cAAc,CAAA;IAC1B,kBAAkB,EAAE,YAAY,CAAA;IAChC,kBAAkB,EAAE,cAAc,GAAG,SAAS,CAAA;IAC9C,uBAAuB,EAAE,cAAc,GAAG,SAAS,CAAA;CACpD,CAAC,CAAA;AAEF,KAAK,oBAAoB,GAAG,QAAQ,CAAC;IACnC,IAAI,EAAE,UAAU,CAAA;IAChB,QAAQ,EAAE,MAAM,IAAI,CAAA;CACrB,CAAC,CAAA;AAEF,KAAK,4BAA4B,GAC7B,wBAAwB,GACxB,oBAAoB,CAAA;AAExB,KAAK,uBAAuB,GAAG,QAAQ,CAAC;IACtC,MAAM,EAAE,uBAAuB,GAAG,SAAS,CAAA;IAC3C,UAAU,EAAE,MAAM,CAAA;CACnB,CAAC,CAAA;AAEF,4EAA4E;AAC5E,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,cAAc,CAAA;IAC1B,kBAAkB,EAAE,YAAY,CAAA;CACjC,CAAC,CAAA;AAEF,eAAO,MAAM,aAAa,EAAE,UAAe,CAAA;AAE3C,eAAO,MAAM,eAAe,WAClB,UAAU,WACT,MAAM,KACd,UAUF,CAAA;AAKD
|
|
1
|
+
{"version":3,"file":"boundary.d.ts","sourceRoot":"","sources":["../../src/html/boundary.ts"],"names":[],"mappings":"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"}
|
package/dist/html/boundary.js
CHANGED
|
@@ -149,8 +149,9 @@ export const restoreBoundaryWrapsForLazyHit = (registry, trackedBoundaries) => {
|
|
|
149
149
|
};
|
|
150
150
|
/** Removes a boundary's wrap when it still matches the descriptor owned by the
|
|
151
151
|
* VNode being destroyed. A replacement registered earlier in the same patch
|
|
152
|
-
* is left intact. Called by `h.submodel`'s
|
|
153
|
-
* VNode
|
|
152
|
+
* is left intact. Called by `h.submodel`'s `postdestroy` hook when snabbdom
|
|
153
|
+
* destroys the corresponding VNode, after every `destroy` hook in that VNode's
|
|
154
|
+
* subtree has run.
|
|
154
155
|
*
|
|
155
156
|
* Does not touch `boundaryDispatches`: it is a WeakMap keyed by
|
|
156
157
|
* outerDispatch, so per-outerDispatch inner Maps become unreachable and
|
|
@@ -183,7 +184,7 @@ export const deregisterBoundaryWrap = (registry, boundaryId, descriptor, mountOu
|
|
|
183
184
|
};
|
|
184
185
|
/** Restores the registry entries replaced by one boundary registration that
|
|
185
186
|
* did not produce a VNode. Used when a Submodel view throws or returns
|
|
186
|
-
* `null`, where no
|
|
187
|
+
* `null`, where no `postdestroy` hook will run and cleanup must undo only that
|
|
187
188
|
* render owner's write without evicting descriptors retained by the
|
|
188
189
|
* currently rendered tree. */
|
|
189
190
|
const rollbackBoundaryWrapRegistration = (registry, boundaryId, descriptor, mountOuterDispatch, previousDescriptor, previousMountDescriptor) => {
|
|
@@ -382,11 +383,10 @@ const dispatchAcrossBoundary = (registry, outerDispatch, boundaryId, message) =>
|
|
|
382
383
|
* which defers the chain lookup to fire time, this snapshots the chain at call
|
|
383
384
|
* time so the resulting thunk survives the boundary being deregistered.
|
|
384
385
|
*
|
|
385
|
-
* Used by `OnUnmount
|
|
386
|
-
*
|
|
387
|
-
*
|
|
388
|
-
*
|
|
389
|
-
* avoids that race. Throws here (at resolve time, boundary alive) if a wrap is
|
|
386
|
+
* Used by `OnUnmount`, whose dispatch runs during teardown or, after a failed
|
|
387
|
+
* replay patch, later still. Resolving eagerly while the chain is live means
|
|
388
|
+
* that dispatch does not depend on what the registry holds at teardown time.
|
|
389
|
+
* Throws here (at resolve time, boundary alive) if a wrap is
|
|
390
390
|
* somehow already missing, surfacing a real corruption rather than misrouting. */
|
|
391
391
|
export const resolveBoundaryDispatchThunk = (registry, outerDispatch, boundaryId, message) => {
|
|
392
392
|
if (boundaryId === ROOT_BOUNDARY) {
|
|
@@ -449,7 +449,7 @@ export const resolveMountBoundaryDispatch = (registry, mountOuterDispatch, bound
|
|
|
449
449
|
* per-render duplicate-slotId tracking map so siblings inside the
|
|
450
450
|
* same parent boundary can be re-validated. Does not touch the wrap
|
|
451
451
|
* or dispatcher tables. Those persist across renders and are evicted
|
|
452
|
-
* by VNode
|
|
452
|
+
* by VNode `postdestroy` hooks instead. */
|
|
453
453
|
export const beginRender = (registry) => {
|
|
454
454
|
registry.seenThisRender.clear();
|
|
455
455
|
registry.dedupeSeen.clear();
|
|
@@ -9,11 +9,11 @@ declare const BRAND = "__childAttribute";
|
|
|
9
9
|
*
|
|
10
10
|
* `resolveUnmount` snapshots the boundary's wrapping chain at the time the
|
|
11
11
|
* group was published (child boundary alive) so `OnUnmount` can dispatch a
|
|
12
|
-
* root message
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
12
|
+
* root message after the boundary has been torn down. `boundaryMappers`
|
|
13
|
+
* snapshots the `toParentMessage` lifts (innermost first) for the Scene test
|
|
14
|
+
* harness. Groups containing `OnMount` also carry `resolveMountDispatch`,
|
|
15
|
+
* which binds the Mount to the acquiring render's dispatch owner while
|
|
16
|
+
* following that owner's current live wrappers.
|
|
17
17
|
*
|
|
18
18
|
* Created via {@link childAttributes}. Element constructors accept
|
|
19
19
|
* `ChildAttribute` alongside `Attribute<Message>` in their attribute
|