@lushly-dev/fast-element 3.0.1-preview.0 → 3.0.1-preview.2
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/CHANGELOG.md +12 -0
- package/dist/command/command.api.json +7857 -0
- package/dist/context/context.api.json +1084 -0
- package/dist/declarative/declarative.api.json +8130 -0
- package/dist/definition-schema/definition-schema.api.json +2689 -0
- package/dist/di/di.api.json +4945 -0
- package/dist/dts/arrays.d.ts +2 -0
- package/dist/dts/binding/binding.d.ts +59 -0
- package/dist/dts/binding/exports.d.ts +9 -0
- package/dist/dts/binding/normalize.d.ts +9 -0
- package/dist/dts/binding/one-time.d.ts +11 -0
- package/dist/dts/binding/one-way.d.ts +20 -0
- package/dist/dts/binding/signal.d.ts +36 -0
- package/dist/dts/binding/two-way.d.ts +44 -0
- package/dist/dts/command/behavior.d.ts +94 -0
- package/dist/dts/command/behaviors/confirm-behavior.d.ts +139 -0
- package/dist/dts/command/behaviors/undo-behavior.d.ts +178 -0
- package/dist/dts/command/command.d.ts +79 -0
- package/dist/dts/command/component-registry.d.ts +50 -0
- package/dist/dts/command/components/confirm-dialog.d.ts +117 -0
- package/dist/dts/command/index.d.ts +21 -0
- package/dist/dts/command/registry.d.ts +201 -0
- package/dist/dts/command/schema-validation.d.ts +45 -0
- package/dist/dts/command/types.d.ts +332 -0
- package/dist/dts/command/validation.d.ts +116 -0
- package/dist/dts/command/weak-ref.d.ts +11 -0
- package/dist/dts/components/attributes.d.ts +153 -0
- package/dist/dts/components/definition-schema-transforms.d.ts +9 -0
- package/dist/dts/components/element-controller.d.ts +349 -0
- package/dist/dts/components/element-hydration.d.ts +2 -0
- package/dist/dts/components/enable-hydration.d.ts +66 -0
- package/dist/dts/components/fast-definitions.d.ts +211 -0
- package/dist/dts/components/fast-element-registry.d.ts +23 -0
- package/dist/dts/components/fast-element.d.ts +91 -0
- package/dist/dts/components/hydration-tracker.d.ts +110 -0
- package/dist/dts/components/hydration.d.ts +52 -0
- package/dist/dts/components/schema.d.ts +205 -0
- package/dist/dts/context.d.ts +171 -0
- package/dist/dts/debug.d.ts +5 -0
- package/dist/dts/declarative/attribute-map.d.ts +58 -0
- package/dist/dts/declarative/debug.d.ts +4 -0
- package/dist/dts/declarative/index.d.ts +14 -0
- package/dist/dts/declarative/interfaces.d.ts +8 -0
- package/dist/dts/declarative/observer-map-utilities.d.ts +58 -0
- package/dist/dts/declarative/observer-map.d.ts +89 -0
- package/dist/dts/declarative/runtime.d.ts +5 -0
- package/dist/dts/declarative/syntax.d.ts +21 -0
- package/dist/dts/declarative/template-bridge.d.ts +33 -0
- package/dist/dts/declarative/template-parser.d.ts +98 -0
- package/dist/dts/declarative/template.d.ts +9 -0
- package/dist/dts/declarative/utilities.d.ts +358 -0
- package/dist/dts/definition-schema/api.d.ts +42 -0
- package/dist/dts/definition-schema/cem.d.ts +78 -0
- package/dist/dts/definition-schema/extension.d.ts +18 -0
- package/dist/dts/definition-schema/extract.d.ts +38 -0
- package/dist/dts/definition-schema/index.d.ts +9 -0
- package/dist/dts/definition-schema/storage.d.ts +35 -0
- package/dist/dts/definition-schema/types.d.ts +176 -0
- package/dist/dts/dev-mode.d.ts +13 -0
- package/dist/dts/di/di.d.ts +894 -0
- package/dist/dts/dom-policy.d.ts +101 -0
- package/dist/dts/dom.d.ts +88 -0
- package/dist/dts/hydration/diagnostics.d.ts +93 -0
- package/dist/dts/hydration/exports.d.ts +18 -0
- package/dist/dts/hydration/hydration-debugger.d.ts +35 -0
- package/dist/dts/hydration/messages.d.ts +62 -0
- package/dist/dts/hydration/runtime.d.ts +7 -0
- package/dist/dts/hydration/target-builder.d.ts +107 -0
- package/dist/dts/index.d.ts +51 -0
- package/dist/dts/index.debug.d.ts +1 -0
- package/dist/dts/index.rollup.d.ts +1 -0
- package/dist/dts/index.rollup.debug.d.ts +1 -0
- package/dist/dts/interfaces.d.ts +106 -0
- package/dist/dts/metadata.d.ts +26 -0
- package/dist/dts/observation/arrays.d.ts +248 -0
- package/dist/dts/observation/notifier.d.ts +127 -0
- package/dist/dts/observation/observable.d.ts +276 -0
- package/dist/dts/observation/update-queue.d.ts +40 -0
- package/dist/dts/observation/volatile.d.ts +9 -0
- package/dist/dts/platform.d.ts +87 -0
- package/dist/dts/registry.d.ts +2 -0
- package/dist/dts/render.d.ts +7 -0
- package/dist/dts/schema.d.ts +1 -0
- package/dist/dts/scoped/detection.d.ts +55 -0
- package/dist/dts/scoped/index.d.ts +68 -0
- package/dist/dts/scoped/mixin.d.ts +118 -0
- package/dist/dts/scoped/registry.d.ts +76 -0
- package/dist/dts/scoped/types.d.ts +48 -0
- package/dist/dts/state/exports.d.ts +3 -0
- package/dist/dts/state/reactive.d.ts +8 -0
- package/dist/dts/state/state.d.ts +141 -0
- package/dist/dts/state/visitor.d.ts +6 -0
- package/dist/dts/state/watch.d.ts +10 -0
- package/dist/dts/styles/css-directive.d.ts +50 -0
- package/dist/dts/styles/css.d.ts +34 -0
- package/dist/dts/styles/element-styles.d.ts +61 -0
- package/dist/dts/styles/host.d.ts +65 -0
- package/dist/dts/styles/style-strategy.d.ts +42 -0
- package/dist/dts/templating/children.d.ts +62 -0
- package/dist/dts/templating/compiler.d.ts +54 -0
- package/dist/dts/templating/html-binding-directive.d.ts +155 -0
- package/dist/dts/templating/html-directive.d.ts +218 -0
- package/dist/dts/templating/html.d.ts +1 -0
- package/dist/dts/templating/hydration-view.d.ts +130 -0
- package/dist/dts/templating/markup.d.ts +48 -0
- package/dist/dts/templating/node-observation.d.ts +99 -0
- package/dist/dts/templating/ref.d.ts +23 -0
- package/dist/dts/templating/render.d.ts +318 -0
- package/dist/dts/templating/repeat.d.ts +131 -0
- package/dist/dts/templating/slotted.d.ts +38 -0
- package/dist/dts/templating/template.d.ts +221 -0
- package/dist/dts/templating/view.d.ts +268 -0
- package/dist/dts/templating/when.d.ts +12 -0
- package/dist/dts/testing/exports.d.ts +3 -0
- package/dist/dts/testing/fakes.d.ts +16 -0
- package/dist/dts/testing/fixture.d.ts +84 -0
- package/dist/dts/testing/models.d.ts +20 -0
- package/dist/dts/testing/timeout.d.ts +7 -0
- package/dist/dts/trust/index.d.ts +8 -0
- package/dist/dts/trust/types.d.ts +48 -0
- package/dist/dts/trust/utils.d.ts +26 -0
- package/dist/dts/tsdoc-metadata.json +11 -0
- package/dist/dts/utilities.d.ts +76 -0
- package/dist/esm/arrays.js +1 -0
- package/dist/esm/binding/binding.js +18 -0
- package/dist/esm/binding/exports.js +6 -0
- package/dist/esm/binding/normalize.js +17 -0
- package/dist/esm/binding/one-time.js +21 -0
- package/dist/esm/binding/one-way.js +30 -0
- package/dist/esm/binding/signal.js +99 -0
- package/dist/esm/binding/two-way.js +109 -0
- package/dist/esm/command/behavior.js +155 -0
- package/dist/esm/command/behaviors/confirm-behavior.js +225 -0
- package/dist/esm/command/behaviors/undo-behavior.js +313 -0
- package/dist/esm/command/command.js +104 -0
- package/dist/esm/command/component-registry.js +107 -0
- package/dist/esm/command/components/confirm-dialog.js +370 -0
- package/dist/esm/command/index.js +22 -0
- package/dist/esm/command/registry.js +755 -0
- package/dist/esm/command/schema-validation.js +194 -0
- package/dist/esm/command/types.js +86 -0
- package/dist/esm/command/validation.js +508 -0
- package/dist/esm/command/weak-ref.js +5 -0
- package/dist/esm/components/attributes.js +219 -0
- package/dist/esm/components/definition-schema-transforms.js +23 -0
- package/dist/esm/components/element-controller.js +840 -0
- package/dist/esm/components/element-hydration.js +2 -0
- package/dist/esm/components/enable-hydration.js +123 -0
- package/dist/esm/components/fast-definitions.js +294 -0
- package/dist/esm/components/fast-element-registry.js +67 -0
- package/dist/esm/components/fast-element.js +82 -0
- package/dist/esm/components/hydration-tracker.js +211 -0
- package/dist/esm/components/hydration.js +187 -0
- package/dist/esm/components/schema.js +253 -0
- package/dist/esm/context.js +185 -0
- package/dist/esm/debug.js +71 -0
- package/dist/esm/declarative/attribute-map.js +122 -0
- package/dist/esm/declarative/debug.js +4 -0
- package/dist/esm/declarative/index.js +10 -0
- package/dist/esm/declarative/interfaces.js +9 -0
- package/dist/esm/declarative/observer-map-utilities.js +565 -0
- package/dist/esm/declarative/observer-map.js +216 -0
- package/dist/esm/declarative/runtime.js +14 -0
- package/dist/esm/declarative/syntax.js +36 -0
- package/dist/esm/declarative/template-bridge.js +160 -0
- package/dist/esm/declarative/template-parser.js +306 -0
- package/dist/esm/declarative/template.js +116 -0
- package/dist/esm/declarative/utilities.js +1069 -0
- package/dist/esm/definition-schema/api.js +129 -0
- package/dist/esm/definition-schema/cem.js +89 -0
- package/dist/esm/definition-schema/extension.js +53 -0
- package/dist/esm/definition-schema/extract.js +167 -0
- package/dist/esm/definition-schema/index.js +8 -0
- package/dist/esm/definition-schema/storage.js +58 -0
- package/dist/esm/definition-schema/types.js +8 -0
- package/dist/esm/dev-mode.js +22 -0
- package/dist/esm/di/di.js +1441 -0
- package/dist/esm/dom-policy.js +374 -0
- package/dist/esm/dom.js +101 -0
- package/dist/esm/hydration/diagnostics.js +50 -0
- package/dist/esm/hydration/exports.js +6 -0
- package/dist/esm/hydration/hydration-debugger.js +112 -0
- package/dist/esm/hydration/messages.js +84 -0
- package/dist/esm/hydration/runtime.js +33 -0
- package/dist/esm/hydration/target-builder.js +264 -0
- package/dist/esm/index.debug.js +3 -0
- package/dist/esm/index.js +49 -0
- package/dist/esm/index.rollup.debug.js +6 -0
- package/dist/esm/index.rollup.js +4 -0
- package/dist/esm/interfaces.js +55 -0
- package/dist/esm/metadata.js +57 -0
- package/dist/esm/observation/arrays.js +661 -0
- package/dist/esm/observation/notifier.js +162 -0
- package/dist/esm/observation/observable.js +324 -0
- package/dist/esm/observation/update-queue.js +56 -0
- package/dist/esm/observation/volatile.js +16 -0
- package/dist/esm/platform.js +98 -0
- package/dist/esm/registry.js +2 -0
- package/dist/esm/render.js +1 -0
- package/dist/esm/schema.js +1 -0
- package/dist/esm/scoped/detection.js +102 -0
- package/dist/esm/scoped/index.js +69 -0
- package/dist/esm/scoped/mixin.js +127 -0
- package/dist/esm/scoped/registry.js +125 -0
- package/dist/esm/scoped/types.js +4 -0
- package/dist/esm/state/exports.js +3 -0
- package/dist/esm/state/reactive.js +34 -0
- package/dist/esm/state/state.js +148 -0
- package/dist/esm/state/visitor.js +28 -0
- package/dist/esm/state/watch.js +36 -0
- package/dist/esm/styles/css-directive.js +36 -0
- package/dist/esm/styles/css.js +56 -0
- package/dist/esm/styles/element-styles.js +144 -0
- package/dist/esm/styles/host.js +1 -0
- package/dist/esm/styles/style-strategy.js +1 -0
- package/dist/esm/templating/children.js +67 -0
- package/dist/esm/templating/compiler.js +359 -0
- package/dist/esm/templating/html-binding-directive.js +288 -0
- package/dist/esm/templating/html-directive.js +113 -0
- package/dist/esm/templating/html.js +1 -0
- package/dist/esm/templating/hydration-view.js +228 -0
- package/dist/esm/templating/markup.js +83 -0
- package/dist/esm/templating/node-observation.js +84 -0
- package/dist/esm/templating/ref.js +21 -0
- package/dist/esm/templating/render.js +468 -0
- package/dist/esm/templating/repeat.js +434 -0
- package/dist/esm/templating/slotted.js +49 -0
- package/dist/esm/templating/template.js +206 -0
- package/dist/esm/templating/view.js +298 -0
- package/dist/esm/templating/when.js +22 -0
- package/dist/esm/testing/exports.js +3 -0
- package/dist/esm/testing/fakes.js +107 -0
- package/dist/esm/testing/fixture.js +86 -0
- package/dist/esm/testing/models.js +58 -0
- package/dist/esm/testing/timeout.js +24 -0
- package/dist/esm/trust/index.js +7 -0
- package/dist/esm/trust/types.js +6 -0
- package/dist/esm/trust/utils.js +126 -0
- package/dist/esm/utilities.js +140 -0
- package/dist/fast-element.api.json +26798 -0
- package/dist/fast-element.d.ts +3985 -0
- package/dist/fast-element.debug.js +7604 -0
- package/dist/fast-element.debug.min.js +3 -0
- package/dist/fast-element.js +7603 -0
- package/dist/fast-element.min.js +3 -0
- package/dist/fast-element.untrimmed.d.ts +4103 -0
- package/dist/observation/arrays/arrays.api.json +2621 -0
- package/dist/scoped/scoped.api.json +891 -0
- package/dist/trust/trust.api.json +629 -0
- package/package.json +21 -23
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized hydration mismatch message strings used by both the default
|
|
3
|
+
* minimal `HydrationDiagnostic` and the opt-in `hydrationDebugger` rich
|
|
4
|
+
* formatter, and by the structural-error throw sites in
|
|
5
|
+
* `target-builder.ts`.
|
|
6
|
+
*
|
|
7
|
+
* Static text is exported as a plain `const`; interpolated text is exported
|
|
8
|
+
* as a small builder function. Plain `export const` declarations tree-shake
|
|
9
|
+
* better than frozen-object property bags, so unused strings drop out of
|
|
10
|
+
* bundles cleanly.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Fallback host tag name used when a hydration mismatch is detected on a
|
|
14
|
+
* node that is not inside a shadow root.
|
|
15
|
+
*/
|
|
16
|
+
export const unknownHostName = "unknown";
|
|
17
|
+
// -- Aspect labels (consumed by the opt-in hydrationDebugger) ----------------
|
|
18
|
+
export const aspectLabelAttribute = "attribute";
|
|
19
|
+
export const aspectLabelBooleanAttribute = "boolean attribute";
|
|
20
|
+
export const aspectLabelProperty = "property";
|
|
21
|
+
export const aspectLabelContent = "content";
|
|
22
|
+
export const aspectLabelTokenList = "token list";
|
|
23
|
+
export const aspectLabelEvent = "event";
|
|
24
|
+
/** Fallback used when the aspectType is missing or unknown. */
|
|
25
|
+
export const aspectLabelUnknown = "binding";
|
|
26
|
+
/**
|
|
27
|
+
* Combines an aspect label with the original source aspect identifier from
|
|
28
|
+
* markup (e.g. `"property className"`). Returns the bare label when no
|
|
29
|
+
* source aspect was captured.
|
|
30
|
+
*/
|
|
31
|
+
export function formatAspect(label, sourceAspect) {
|
|
32
|
+
return sourceAspect ? `${label} \`${sourceAspect}\`` : label;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Formats the "Expected" half of the rich hydration mismatch message, e.g.
|
|
36
|
+
* `"<span> with content binding"` or `"content binding"` when no tag is
|
|
37
|
+
* associated with the binding factory.
|
|
38
|
+
*/
|
|
39
|
+
export function formatExpectedTarget(tagName, aspect) {
|
|
40
|
+
return tagName
|
|
41
|
+
? `<${tagName.toLowerCase()}> with ${aspect} binding`
|
|
42
|
+
: `${aspect} binding`;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Default minimal hydration mismatch message used when the
|
|
46
|
+
* `hydrationDebugger` opt-in is not installed. The optional `detail` string
|
|
47
|
+
* carries the structural expectation surfaced by `target-builder.ts`.
|
|
48
|
+
*/
|
|
49
|
+
export function formatDefaultMismatchMessage(hostName, detail) {
|
|
50
|
+
const suffix = detail ? `: ${detail}` : "";
|
|
51
|
+
return (`Hydration mismatch in <${hostName}>${suffix}. Install ` +
|
|
52
|
+
`hydrationDebugger() from "@lushly-dev/fast-element/hydration.js" and ` +
|
|
53
|
+
`pass it as enableHydration({ debugger: hydrationDebugger() }) for an ` +
|
|
54
|
+
`"Expected / Received" report including the SSR HTML snippet.`);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Rich `Expected … / Received …` hydration mismatch message format produced
|
|
58
|
+
* by the `hydrationDebugger` formatter.
|
|
59
|
+
*/
|
|
60
|
+
export function formatRichMismatchMessage(hostName, expectedText, receivedHtml) {
|
|
61
|
+
return (`Hydration mismatch in <${hostName}>.\n` +
|
|
62
|
+
` Expected: ${expectedText}\n` +
|
|
63
|
+
` Received: ${receivedHtml}`);
|
|
64
|
+
}
|
|
65
|
+
// -- Structural expectations (used by target-builder.ts throw sites) ---------
|
|
66
|
+
export const expectedContentAfterStartMarker = "content following `<!--fe:b-->` content binding marker";
|
|
67
|
+
export const expectedContentEndMarker = "matching `<!--fe:/b-->` content binding close marker";
|
|
68
|
+
export const expectedElementBoundaryEndMarker = "matching `<!--fe:/e-->` element boundary close marker";
|
|
69
|
+
/**
|
|
70
|
+
* Builds the "no more attribute bindings" structural expectation message
|
|
71
|
+
* thrown when an element's `data-fe` count claims more attribute bindings
|
|
72
|
+
* than the compiled template defines.
|
|
73
|
+
*/
|
|
74
|
+
export function formatNoMoreAttributeBindings(factoryCount) {
|
|
75
|
+
return `no more attribute bindings (template defines ${factoryCount})`;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Builds the "no more content bindings" structural expectation message
|
|
79
|
+
* thrown when the SSR DOM contains more content binding markers than the
|
|
80
|
+
* compiled template defines.
|
|
81
|
+
*/
|
|
82
|
+
export function formatNoMoreContentBindings(factoryCount) {
|
|
83
|
+
return `no more content bindings (template defines ${factoryCount})`;
|
|
84
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Hydratable } from "../components/hydration.js";
|
|
2
|
+
import { ViewTemplate } from "../templating/template.js";
|
|
3
|
+
import { HydrationView } from "../templating/hydration-view.js";
|
|
4
|
+
let installed = false;
|
|
5
|
+
/**
|
|
6
|
+
* Installs the hydration runtime on `ViewTemplate.prototype`,
|
|
7
|
+
* making all templates hydratable. Call this before any hydration
|
|
8
|
+
* occurs. Safe to call multiple times — subsequent calls are no-ops.
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export function ensureHydrationRuntime() {
|
|
12
|
+
if (installed) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const prototype = ViewTemplate.prototype;
|
|
16
|
+
if (prototype[Hydratable] !== Hydratable) {
|
|
17
|
+
Object.defineProperties(prototype, {
|
|
18
|
+
[Hydratable]: {
|
|
19
|
+
value: Hydratable,
|
|
20
|
+
enumerable: false,
|
|
21
|
+
configurable: false,
|
|
22
|
+
},
|
|
23
|
+
hydrate: {
|
|
24
|
+
value(firstChild, lastChild, hostBindingTarget) {
|
|
25
|
+
return new HydrationView(firstChild, lastChild, this, hostBindingTarget);
|
|
26
|
+
},
|
|
27
|
+
enumerable: true,
|
|
28
|
+
configurable: false,
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
installed = true;
|
|
33
|
+
}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { HydrationMarkup } from "../components/hydration.js";
|
|
2
|
+
import { getHostName, getHydrationDiagnostic, } from "./diagnostics.js";
|
|
3
|
+
import { expectedContentAfterStartMarker, expectedContentEndMarker, expectedElementBoundaryEndMarker, formatNoMoreAttributeBindings, formatNoMoreContentBindings, } from "./messages.js";
|
|
4
|
+
export class HydrationTargetElementError extends Error {
|
|
5
|
+
constructor(
|
|
6
|
+
/**
|
|
7
|
+
* The error message
|
|
8
|
+
*/
|
|
9
|
+
message,
|
|
10
|
+
/**
|
|
11
|
+
* The Compiled View Behavior Factories that belong to the view.
|
|
12
|
+
*/
|
|
13
|
+
factories,
|
|
14
|
+
/**
|
|
15
|
+
* The node to target factory.
|
|
16
|
+
*/
|
|
17
|
+
node,
|
|
18
|
+
/**
|
|
19
|
+
* Structured description of the binding the hydration walk was
|
|
20
|
+
* attempting to apply when the mismatch was detected. Free-form
|
|
21
|
+
* string for structural errors that do not correspond to a single
|
|
22
|
+
* binding factory.
|
|
23
|
+
*/
|
|
24
|
+
expected,
|
|
25
|
+
/**
|
|
26
|
+
* Structured description of the server-rendered DOM that was
|
|
27
|
+
* encountered at the mismatch point.
|
|
28
|
+
*/
|
|
29
|
+
received) {
|
|
30
|
+
super(message);
|
|
31
|
+
this.factories = factories;
|
|
32
|
+
this.node = node;
|
|
33
|
+
this.expected = expected;
|
|
34
|
+
this.received = received;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function isComment(node) {
|
|
38
|
+
return node.nodeType === Node.COMMENT_NODE;
|
|
39
|
+
}
|
|
40
|
+
function isText(node) {
|
|
41
|
+
return node.nodeType === Node.TEXT_NODE;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Returns a range object inclusive of all nodes including and between the
|
|
45
|
+
* provided first and last node.
|
|
46
|
+
* @param first - The first node
|
|
47
|
+
* @param last - This last node
|
|
48
|
+
* @returns
|
|
49
|
+
*/
|
|
50
|
+
export function createRangeForNodes(first, last) {
|
|
51
|
+
const range = document.createRange();
|
|
52
|
+
range.setStart(first, 0);
|
|
53
|
+
// The lastIndex should be inclusive of the end of the lastChild. Obtain offset based
|
|
54
|
+
// on usageNotes: https://developer.mozilla.org/en-US/docs/Web/API/Range/setEnd#usage_notes
|
|
55
|
+
range.setEnd(last, isComment(last) || isText(last) ? last.data.length : last.childNodes.length);
|
|
56
|
+
return range;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Maps compiled ViewBehaviorFactory IDs to their corresponding DOM nodes in the
|
|
60
|
+
* server-rendered shadow root. Uses a TreeWalker to scan the existing DOM between
|
|
61
|
+
* firstNode and lastNode, processing data-free sequential hydration markers.
|
|
62
|
+
*
|
|
63
|
+
* A sequential factory pointer advances through the factories array in DFS order.
|
|
64
|
+
* Since the template compiler and hydration walker both traverse the DOM in
|
|
65
|
+
* identical depth-first order, no embedded indices are needed in markers.
|
|
66
|
+
*
|
|
67
|
+
* For element nodes: parses `data-fe="N"` to determine the count of attribute
|
|
68
|
+
* binding factories, then consumes N factories sequentially.
|
|
69
|
+
*
|
|
70
|
+
* For comment nodes: `fe:b` markers consume the next factory for content bindings,
|
|
71
|
+
* using balanced depth counting for nested marker pairing. `fe:e` markers cause
|
|
72
|
+
* the walker to skip nested custom element subtrees.
|
|
73
|
+
*
|
|
74
|
+
* Host bindings (targetNodeId='h') appear at the start of the factories array but
|
|
75
|
+
* have no SSR markers — getHydrationIndexOffset() computes the initial pointer value.
|
|
76
|
+
*
|
|
77
|
+
* @param firstNode - The first node of the view.
|
|
78
|
+
* @param lastNode - The last node of the view.
|
|
79
|
+
* @param factories - The Compiled View Behavior Factories that belong to the view.
|
|
80
|
+
* @returns - A {@link ViewBehaviorTargets } object for the factories in the view.
|
|
81
|
+
*/
|
|
82
|
+
export function buildViewBindingTargets(firstNode, lastNode, factories) {
|
|
83
|
+
const range = createRangeForNodes(firstNode, lastNode);
|
|
84
|
+
const treeRoot = range.commonAncestorContainer;
|
|
85
|
+
const walker = document.createTreeWalker(treeRoot, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_COMMENT + NodeFilter.SHOW_TEXT, {
|
|
86
|
+
acceptNode(node) {
|
|
87
|
+
return range.comparePoint(node, 0) === 0
|
|
88
|
+
? NodeFilter.FILTER_ACCEPT
|
|
89
|
+
: NodeFilter.FILTER_REJECT;
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
const targets = {};
|
|
93
|
+
const boundaries = {};
|
|
94
|
+
// Sequential factory pointer — skip host bindings at the start
|
|
95
|
+
const hydrationIndexOffset = getHydrationIndexOffset(factories);
|
|
96
|
+
let factoryPointer = hydrationIndexOffset;
|
|
97
|
+
let node = (walker.currentNode = firstNode);
|
|
98
|
+
while (node !== null) {
|
|
99
|
+
switch (node.nodeType) {
|
|
100
|
+
case Node.ELEMENT_NODE: {
|
|
101
|
+
const element = node;
|
|
102
|
+
const legacyIndices = HydrationMarkup.parseLegacyAttributeBindingIndices(element);
|
|
103
|
+
if (legacyIndices !== null) {
|
|
104
|
+
for (const index of legacyIndices) {
|
|
105
|
+
const factoryIndex = index + hydrationIndexOffset;
|
|
106
|
+
const factory = factories[factoryIndex];
|
|
107
|
+
if (!factory) {
|
|
108
|
+
const expected = formatNoMoreAttributeBindings(factories.length);
|
|
109
|
+
const result = getHydrationDiagnostic().formatStructuralError(node, getHostName(node), expected);
|
|
110
|
+
throw new HydrationTargetElementError(result.message, factories, element, result.expected, result.received);
|
|
111
|
+
}
|
|
112
|
+
targetFactory(factory, node, targets);
|
|
113
|
+
factoryPointer = Math.max(factoryPointer, factoryIndex + 1);
|
|
114
|
+
}
|
|
115
|
+
HydrationMarkup.removeLegacyAttributeBindingMarkers(element);
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
const count = HydrationMarkup.parseAttributeBindingCount(element);
|
|
119
|
+
if (count !== null) {
|
|
120
|
+
for (let i = 0; i < count; i++) {
|
|
121
|
+
const factory = factories[factoryPointer++];
|
|
122
|
+
if (!factory) {
|
|
123
|
+
const expected = formatNoMoreAttributeBindings(factories.length);
|
|
124
|
+
const result = getHydrationDiagnostic().formatStructuralError(node, getHostName(node), expected);
|
|
125
|
+
throw new HydrationTargetElementError(result.message, factories, node, result.expected, result.received);
|
|
126
|
+
}
|
|
127
|
+
targetFactory(factory, node, targets);
|
|
128
|
+
}
|
|
129
|
+
element.removeAttribute(HydrationMarkup.attributeMarkerName);
|
|
130
|
+
}
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
case Node.COMMENT_NODE: {
|
|
134
|
+
const data = node.data;
|
|
135
|
+
if (HydrationMarkup.isElementBoundaryStartMarker(node)) {
|
|
136
|
+
// Element boundary — clear start marker and skip subtree
|
|
137
|
+
node.data = "";
|
|
138
|
+
skipToElementBoundaryEnd(walker, factories, node);
|
|
139
|
+
}
|
|
140
|
+
else if (HydrationMarkup.isContentBindingStartMarker(data)) {
|
|
141
|
+
// Content binding — consume next factory
|
|
142
|
+
const legacyIndex = HydrationMarkup.parseLegacyContentBindingStartIndex(data);
|
|
143
|
+
const factoryIndex = legacyIndex === null
|
|
144
|
+
? factoryPointer++
|
|
145
|
+
: legacyIndex + hydrationIndexOffset;
|
|
146
|
+
const factory = factories[factoryIndex];
|
|
147
|
+
factoryPointer = Math.max(factoryPointer, factoryIndex + 1);
|
|
148
|
+
if (!factory) {
|
|
149
|
+
const expected = formatNoMoreContentBindings(factories.length);
|
|
150
|
+
const result = getHydrationDiagnostic().formatStructuralError(node, getHostName(node), expected);
|
|
151
|
+
throw new HydrationTargetElementError(result.message, factories, node, result.expected, result.received);
|
|
152
|
+
}
|
|
153
|
+
targetContentBinding(node, walker, factory, factories, targets, boundaries);
|
|
154
|
+
}
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
node = walker.nextNode();
|
|
159
|
+
}
|
|
160
|
+
range.detach();
|
|
161
|
+
return { targets, boundaries };
|
|
162
|
+
}
|
|
163
|
+
function targetContentBinding(node, walker, factory, factories, targets, boundaries) {
|
|
164
|
+
const nodes = [];
|
|
165
|
+
let current = walker.nextSibling();
|
|
166
|
+
node.data = "";
|
|
167
|
+
if (current === null) {
|
|
168
|
+
const expected = expectedContentAfterStartMarker;
|
|
169
|
+
const result = getHydrationDiagnostic().formatStructuralError(node, getHostName(node), expected);
|
|
170
|
+
throw new HydrationTargetElementError(result.message, factories, node, result.expected, result.received);
|
|
171
|
+
}
|
|
172
|
+
const first = current;
|
|
173
|
+
// Balanced depth counting for nested content markers
|
|
174
|
+
let depth = 0;
|
|
175
|
+
while (current !== null) {
|
|
176
|
+
if (isComment(current)) {
|
|
177
|
+
if (HydrationMarkup.isContentBindingStartMarker(current.data)) {
|
|
178
|
+
depth++;
|
|
179
|
+
}
|
|
180
|
+
else if (HydrationMarkup.isContentBindingEndMarker(current.data)) {
|
|
181
|
+
if (depth === 0)
|
|
182
|
+
break;
|
|
183
|
+
depth--;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
nodes.push(current);
|
|
187
|
+
current = walker.nextSibling();
|
|
188
|
+
}
|
|
189
|
+
if (current === null) {
|
|
190
|
+
const expected = expectedContentEndMarker;
|
|
191
|
+
const result = getHydrationDiagnostic().formatStructuralError(node, getHostName(node), expected);
|
|
192
|
+
throw new HydrationTargetElementError(result.message, factories, node, result.expected, result.received);
|
|
193
|
+
}
|
|
194
|
+
current.data = "";
|
|
195
|
+
if (nodes.length === 1 && isText(nodes[0])) {
|
|
196
|
+
targetFactory(factory, nodes[0], targets);
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
// If current === first, it means there is no content in
|
|
200
|
+
// the view. This happens when a `when` directive evaluates false,
|
|
201
|
+
// or whenever a content binding returns null or undefined.
|
|
202
|
+
if (current !== first && current.previousSibling !== null) {
|
|
203
|
+
boundaries[factory.targetNodeId] = {
|
|
204
|
+
first,
|
|
205
|
+
last: current.previousSibling,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
// Insert a text node so text content binding targets it
|
|
209
|
+
const dummyTextNode = current.parentNode.insertBefore(document.createTextNode(""), current);
|
|
210
|
+
targetFactory(factory, dummyTextNode, targets);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Skips past a nested custom element's shadow content using balanced
|
|
215
|
+
* depth counting to handle nested element boundaries correctly.
|
|
216
|
+
*/
|
|
217
|
+
function skipToElementBoundaryEnd(walker, factories, startNode) {
|
|
218
|
+
let depth = 0;
|
|
219
|
+
let current = walker.nextSibling();
|
|
220
|
+
while (current !== null) {
|
|
221
|
+
if (isComment(current)) {
|
|
222
|
+
if (HydrationMarkup.isElementBoundaryStartMarker(current)) {
|
|
223
|
+
current.data = "";
|
|
224
|
+
depth++;
|
|
225
|
+
}
|
|
226
|
+
else if (HydrationMarkup.isElementBoundaryEndMarker(current)) {
|
|
227
|
+
if (depth === 0) {
|
|
228
|
+
current.data = "";
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
current.data = "";
|
|
232
|
+
depth--;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
current = walker.nextSibling();
|
|
236
|
+
}
|
|
237
|
+
const expected = expectedElementBoundaryEndMarker;
|
|
238
|
+
const result = getHydrationDiagnostic().formatStructuralError(startNode, getHostName(startNode), expected);
|
|
239
|
+
throw new HydrationTargetElementError(result.message, factories, startNode, result.expected, result.received);
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Counts how many factories at the start of the array are host bindings (targetNodeId='h').
|
|
243
|
+
* Host bindings target the custom element itself and are not represented by SSR markers,
|
|
244
|
+
* so the factory pointer must start past them.
|
|
245
|
+
*/
|
|
246
|
+
function getHydrationIndexOffset(factories) {
|
|
247
|
+
let offset = 0;
|
|
248
|
+
for (let i = 0, ii = factories.length; i < ii; ++i) {
|
|
249
|
+
if (factories[i].targetNodeId === "h") {
|
|
250
|
+
offset++;
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return offset;
|
|
257
|
+
}
|
|
258
|
+
export function targetFactory(factory, node, targets) {
|
|
259
|
+
if (factory.targetNodeId === undefined) {
|
|
260
|
+
// Dev error, this shouldn't ever be thrown
|
|
261
|
+
throw new Error("Factory could not be target to the node");
|
|
262
|
+
}
|
|
263
|
+
targets[factory.targetNodeId] = node;
|
|
264
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core APIs for building standards-based Web Components with FAST Element.
|
|
3
|
+
* @packageDocumentation
|
|
4
|
+
*/
|
|
5
|
+
// Binding
|
|
6
|
+
export { Binding } from "./binding/binding.js";
|
|
7
|
+
export { normalizeBinding } from "./binding/normalize.js";
|
|
8
|
+
export { oneTime } from "./binding/one-time.js";
|
|
9
|
+
export { listener, oneWay } from "./binding/one-way.js";
|
|
10
|
+
export { Signal, signal } from "./binding/signal.js";
|
|
11
|
+
export { TwoWaySettings, twoWay, } from "./binding/two-way.js";
|
|
12
|
+
// Components
|
|
13
|
+
export { AttributeConfiguration, AttributeDefinition, attr, booleanConverter, nullableBooleanConverter, nullableNumberConverter, } from "./components/attributes.js";
|
|
14
|
+
export { ElementController, Stages, } from "./components/element-controller.js";
|
|
15
|
+
export { FASTElementDefinition } from "./components/fast-definitions.js";
|
|
16
|
+
export { customElement, FASTElement, } from "./components/fast-element.js";
|
|
17
|
+
export { fastElementRegistry, } from "./components/fast-element-registry.js";
|
|
18
|
+
export { enableDebug } from "./debug.js";
|
|
19
|
+
export { DOM, DOMAspect } from "./dom.js";
|
|
20
|
+
export { DOMPolicy, } from "./dom-policy.js";
|
|
21
|
+
export { ArrayObserver, lengthOf, Sort, Splice, SpliceStrategy, SpliceStrategySupport, sortedCount, } from "./observation/arrays.js";
|
|
22
|
+
// Observation
|
|
23
|
+
export { PropertyChangeNotifier, SubscriberSet, } from "./observation/notifier.js";
|
|
24
|
+
export { ExecutionContext, Observable, observable, SourceLifetime, } from "./observation/observable.js";
|
|
25
|
+
export { Updates } from "./observation/update-queue.js";
|
|
26
|
+
export { volatile } from "./observation/volatile.js";
|
|
27
|
+
export { emptyArray, FAST } from "./platform.js";
|
|
28
|
+
export { Schema, schemaRegistry, } from "./schema.js";
|
|
29
|
+
export * from "./state/exports.js";
|
|
30
|
+
// Styles
|
|
31
|
+
export { css } from "./styles/css.js";
|
|
32
|
+
export { CSSDirective, cssDirective, } from "./styles/css-directive.js";
|
|
33
|
+
export { ElementStyles } from "./styles/element-styles.js";
|
|
34
|
+
// Directives
|
|
35
|
+
export { ChildrenDirective, children, } from "./templating/children.js";
|
|
36
|
+
// Templating
|
|
37
|
+
export { Compiler } from "./templating/compiler.js";
|
|
38
|
+
export { HTMLBindingDirective, } from "./templating/html-binding-directive.js";
|
|
39
|
+
export { HTMLDirective, htmlDirective, StatelessAttachedAttributeDirective, } from "./templating/html-directive.js";
|
|
40
|
+
export { Markup, Parser } from "./templating/markup.js";
|
|
41
|
+
export { elements, NodeObservationDirective, } from "./templating/node-observation.js";
|
|
42
|
+
export { RefDirective, ref } from "./templating/ref.js";
|
|
43
|
+
export { RenderBehavior, RenderDirective, render } from "./templating/render.js";
|
|
44
|
+
export { RepeatBehavior, RepeatDirective, repeat, } from "./templating/repeat.js";
|
|
45
|
+
export { SlottedDirective, slotted, } from "./templating/slotted.js";
|
|
46
|
+
export { html, InlineTemplateDirective, ViewTemplate, } from "./templating/template.js";
|
|
47
|
+
export { DefaultExecutionContext, HTMLView, } from "./templating/view.js";
|
|
48
|
+
export { when } from "./templating/when.js";
|
|
49
|
+
export * from "./utilities.js";
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Warning and error messages.
|
|
3
|
+
* @internal
|
|
4
|
+
*/
|
|
5
|
+
export var Message;
|
|
6
|
+
(function (Message) {
|
|
7
|
+
// 1000 - 1100 Kernel
|
|
8
|
+
// 1101 - 1200 Observation
|
|
9
|
+
Message[Message["needsArrayObservation"] = 1101] = "needsArrayObservation";
|
|
10
|
+
// 1201 - 1300 Templating
|
|
11
|
+
Message[Message["onlySetDOMPolicyOnce"] = 1201] = "onlySetDOMPolicyOnce";
|
|
12
|
+
Message[Message["bindingInnerHTMLRequiresTrustedTypes"] = 1202] = "bindingInnerHTMLRequiresTrustedTypes";
|
|
13
|
+
Message[Message["twoWayBindingRequiresObservables"] = 1203] = "twoWayBindingRequiresObservables";
|
|
14
|
+
Message[Message["hostBindingWithoutHost"] = 1204] = "hostBindingWithoutHost";
|
|
15
|
+
Message[Message["unsupportedBindingBehavior"] = 1205] = "unsupportedBindingBehavior";
|
|
16
|
+
Message[Message["directCallToHTMLTagNotAllowed"] = 1206] = "directCallToHTMLTagNotAllowed";
|
|
17
|
+
Message[Message["onlySetTemplatePolicyOnce"] = 1207] = "onlySetTemplatePolicyOnce";
|
|
18
|
+
Message[Message["cannotSetTemplatePolicyAfterCompilation"] = 1208] = "cannotSetTemplatePolicyAfterCompilation";
|
|
19
|
+
Message[Message["blockedByDOMPolicy"] = 1209] = "blockedByDOMPolicy";
|
|
20
|
+
Message[Message["invalidHydrationAttributeMarker"] = 1210] = "invalidHydrationAttributeMarker";
|
|
21
|
+
Message[Message["duplicateRenderInstruction"] = 1211] = "duplicateRenderInstruction";
|
|
22
|
+
// 1301 - 1400 Styles
|
|
23
|
+
// 1401 - 1500 Components
|
|
24
|
+
Message[Message["missingElementDefinition"] = 1401] = "missingElementDefinition";
|
|
25
|
+
// 1501 - 1600 Context and Dependency Injection
|
|
26
|
+
Message[Message["noRegistrationForContext"] = 1501] = "noRegistrationForContext";
|
|
27
|
+
Message[Message["noFactoryForResolver"] = 1502] = "noFactoryForResolver";
|
|
28
|
+
Message[Message["invalidResolverStrategy"] = 1503] = "invalidResolverStrategy";
|
|
29
|
+
Message[Message["cannotAutoregisterDependency"] = 1504] = "cannotAutoregisterDependency";
|
|
30
|
+
Message[Message["cannotResolveKey"] = 1505] = "cannotResolveKey";
|
|
31
|
+
Message[Message["cannotConstructNativeFunction"] = 1506] = "cannotConstructNativeFunction";
|
|
32
|
+
Message[Message["cannotJITRegisterNonConstructor"] = 1507] = "cannotJITRegisterNonConstructor";
|
|
33
|
+
Message[Message["cannotJITRegisterIntrinsic"] = 1508] = "cannotJITRegisterIntrinsic";
|
|
34
|
+
Message[Message["cannotJITRegisterInterface"] = 1509] = "cannotJITRegisterInterface";
|
|
35
|
+
Message[Message["invalidResolver"] = 1510] = "invalidResolver";
|
|
36
|
+
Message[Message["invalidKey"] = 1511] = "invalidKey";
|
|
37
|
+
Message[Message["noDefaultResolver"] = 1512] = "noDefaultResolver";
|
|
38
|
+
Message[Message["cyclicDependency"] = 1513] = "cyclicDependency";
|
|
39
|
+
Message[Message["connectUpdateRequiresController"] = 1514] = "connectUpdateRequiresController";
|
|
40
|
+
})(Message || (Message = {}));
|
|
41
|
+
/**
|
|
42
|
+
* Determines whether or not an object is a function.
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
export const isFunction = (object) => typeof object === "function";
|
|
46
|
+
/**
|
|
47
|
+
* Determines whether or not an object is a string.
|
|
48
|
+
* @public
|
|
49
|
+
*/
|
|
50
|
+
export const isString = (object) => typeof object === "string";
|
|
51
|
+
/**
|
|
52
|
+
* A function which does nothing.
|
|
53
|
+
* @public
|
|
54
|
+
*/
|
|
55
|
+
export const noop = () => void 0;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { emptyArray } from "./platform.js";
|
|
2
|
+
// Tiny polyfill for TypeScript's Reflect metadata API.
|
|
3
|
+
const metadataByTarget = new Map();
|
|
4
|
+
if (!("metadata" in Reflect)) {
|
|
5
|
+
Reflect.metadata = function (key, value) {
|
|
6
|
+
return function (target) {
|
|
7
|
+
Reflect.defineMetadata(key, value, target);
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
Reflect.defineMetadata = function (key, value, target) {
|
|
11
|
+
let metadata = metadataByTarget.get(target);
|
|
12
|
+
if (metadata === void 0) {
|
|
13
|
+
metadataByTarget.set(target, (metadata = new Map()));
|
|
14
|
+
}
|
|
15
|
+
metadata.set(key, value);
|
|
16
|
+
};
|
|
17
|
+
Reflect.getOwnMetadata = function (key, target) {
|
|
18
|
+
const metadata = metadataByTarget.get(target);
|
|
19
|
+
if (metadata !== void 0) {
|
|
20
|
+
return metadata.get(key);
|
|
21
|
+
}
|
|
22
|
+
return void 0;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const annotationParamTypesKey = "annotation:paramtypes";
|
|
26
|
+
const designParamTypesKey = "design:paramtypes";
|
|
27
|
+
/**
|
|
28
|
+
* Provides basic metadata capabilities used by Context and Dependency Injection.
|
|
29
|
+
* @public
|
|
30
|
+
*/
|
|
31
|
+
export const Metadata = Object.freeze({
|
|
32
|
+
/**
|
|
33
|
+
* Gets the "design:paramtypes" metadata for the specified type.
|
|
34
|
+
* @param Type - The type to get the metadata for.
|
|
35
|
+
* @returns The metadata array or a frozen empty array if no metadata is found.
|
|
36
|
+
*/
|
|
37
|
+
getDesignParamTypes: (Type) => { var _a; return ((_a = Reflect.getOwnMetadata(designParamTypesKey, Type)) !== null && _a !== void 0 ? _a : emptyArray); },
|
|
38
|
+
/**
|
|
39
|
+
* Gets the "annotation:paramtypes" metadata for the specified type.
|
|
40
|
+
* @param Type - The type to get the metadata for.
|
|
41
|
+
* @returns The metadata array or a frozen empty array if no metadata is found.
|
|
42
|
+
*/
|
|
43
|
+
getAnnotationParamTypes: (Type) => { var _a; return ((_a = Reflect.getOwnMetadata(annotationParamTypesKey, Type)) !== null && _a !== void 0 ? _a : emptyArray); },
|
|
44
|
+
/**
|
|
45
|
+
* Gets the "annotation:paramtypes" metadata for the specified type. If none is found,
|
|
46
|
+
* an empty, mutable metadata array is created and added.
|
|
47
|
+
* @param Type - The type to get or create the metadata for.
|
|
48
|
+
* @returns A mutable metadata array.
|
|
49
|
+
*/
|
|
50
|
+
getOrCreateAnnotationParamTypes(Type) {
|
|
51
|
+
let types = this.getAnnotationParamTypes(Type);
|
|
52
|
+
if (types === emptyArray) {
|
|
53
|
+
Reflect.defineMetadata(annotationParamTypesKey, (types = []), Type);
|
|
54
|
+
}
|
|
55
|
+
return types;
|
|
56
|
+
},
|
|
57
|
+
});
|