@getodk/xforms-engine 0.1.1 → 0.2.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/body/BodyDefinition.d.ts +24 -7
- package/dist/body/RepeatElementDefinition.d.ts +19 -0
- package/dist/body/appearance/inputAppearanceParser.d.ts +4 -0
- package/dist/body/appearance/selectAppearanceParser.d.ts +4 -0
- package/dist/body/appearance/structureElementAppearanceParser.d.ts +4 -0
- package/dist/body/control/ControlDefinition.d.ts +2 -0
- package/dist/body/control/InputDefinition.d.ts +5 -0
- package/dist/body/control/select/SelectDefinition.d.ts +11 -1
- package/dist/body/group/BaseGroupDefinition.d.ts +3 -8
- package/dist/body/text/LabelDefinition.d.ts +2 -0
- package/dist/body/text/TextElementDefinition.d.ts +3 -3
- package/dist/client/BaseNode.d.ts +6 -1
- package/dist/client/GroupNode.d.ts +5 -2
- package/dist/client/NodeAppearances.d.ts +15 -0
- package/dist/client/RepeatInstanceNode.d.ts +3 -0
- package/dist/client/RepeatRangeNode.d.ts +5 -2
- package/dist/client/RootNode.d.ts +19 -0
- package/dist/client/SelectNode.d.ts +3 -0
- package/dist/client/StringNode.d.ts +3 -0
- package/dist/client/SubtreeNode.d.ts +1 -0
- package/dist/index.js +624 -368
- package/dist/index.js.map +1 -1
- package/dist/instance/Group.d.ts +3 -3
- package/dist/instance/RepeatInstance.d.ts +26 -2
- package/dist/instance/RepeatRange.d.ts +84 -5
- package/dist/instance/Root.d.ts +8 -23
- package/dist/instance/SelectField.d.ts +2 -2
- package/dist/instance/StringField.d.ts +2 -2
- package/dist/instance/Subtree.d.ts +1 -1
- package/dist/instance/abstract/DescendantNode.d.ts +12 -4
- package/dist/instance/abstract/InstanceNode.d.ts +26 -29
- package/dist/instance/internal-api/EvaluationContext.d.ts +5 -4
- package/dist/instance/internal-api/ValueContext.d.ts +2 -2
- package/dist/lib/TokenListParser.d.ts +84 -0
- package/dist/lib/dom/query.d.ts +5 -0
- package/dist/lib/reactivity/materializeCurrentStateChildren.d.ts +2 -1
- package/dist/model/DescendentNodeDefinition.d.ts +1 -2
- package/dist/model/NodeDefinition.d.ts +12 -12
- package/dist/model/RepeatInstanceDefinition.d.ts +5 -6
- package/dist/model/{RepeatSequenceDefinition.d.ts → RepeatRangeDefinition.d.ts} +4 -4
- package/dist/model/RepeatTemplateDefinition.d.ts +6 -7
- package/dist/model/RootDefinition.d.ts +3 -1
- package/dist/model/SubtreeDefinition.d.ts +2 -2
- package/dist/model/ValueNodeDefinition.d.ts +2 -3
- package/dist/solid.js +625 -369
- package/dist/solid.js.map +1 -1
- package/package.json +2 -2
- package/src/XFormDOM.ts +81 -8
- package/src/body/BodyDefinition.ts +38 -23
- package/src/body/RepeatElementDefinition.ts +70 -0
- package/src/body/appearance/inputAppearanceParser.ts +39 -0
- package/src/body/appearance/selectAppearanceParser.ts +38 -0
- package/src/body/appearance/structureElementAppearanceParser.ts +7 -0
- package/src/body/control/ControlDefinition.ts +4 -0
- package/src/body/control/InputDefinition.ts +13 -0
- package/src/body/control/select/SelectDefinition.ts +14 -5
- package/src/body/group/BaseGroupDefinition.ts +11 -49
- package/src/body/text/LabelDefinition.ts +15 -1
- package/src/body/text/TextElementDefinition.ts +5 -5
- package/src/client/BaseNode.ts +9 -1
- package/src/client/GroupNode.ts +6 -2
- package/src/client/NodeAppearances.ts +22 -0
- package/src/client/RepeatInstanceNode.ts +4 -0
- package/src/client/RepeatRangeNode.ts +6 -2
- package/src/client/RootNode.ts +22 -0
- package/src/client/SelectNode.ts +4 -0
- package/src/client/StringNode.ts +4 -0
- package/src/client/SubtreeNode.ts +1 -0
- package/src/instance/Group.ts +14 -9
- package/src/instance/RepeatInstance.ts +59 -15
- package/src/instance/RepeatRange.ts +133 -15
- package/src/instance/Root.ts +20 -64
- package/src/instance/SelectField.ts +7 -7
- package/src/instance/StringField.ts +8 -7
- package/src/instance/Subtree.ts +10 -7
- package/src/instance/abstract/DescendantNode.ts +45 -43
- package/src/instance/abstract/InstanceNode.ts +69 -86
- package/src/instance/children.ts +17 -7
- package/src/instance/index.ts +1 -1
- package/src/instance/internal-api/EvaluationContext.ts +5 -6
- package/src/instance/internal-api/ValueContext.ts +2 -2
- package/src/lib/TokenListParser.ts +156 -0
- package/src/lib/dom/query.ts +13 -0
- package/src/lib/reactivity/createChildrenState.ts +51 -6
- package/src/lib/reactivity/createComputedExpression.ts +1 -1
- package/src/lib/reactivity/createSelectItems.ts +4 -6
- package/src/lib/reactivity/createValueState.ts +6 -6
- package/src/lib/reactivity/materializeCurrentStateChildren.ts +3 -1
- package/src/model/DescendentNodeDefinition.ts +1 -2
- package/src/model/ModelDefinition.ts +1 -1
- package/src/model/NodeDefinition.ts +12 -12
- package/src/model/RepeatInstanceDefinition.ts +8 -13
- package/src/model/{RepeatSequenceDefinition.ts → RepeatRangeDefinition.ts} +6 -6
- package/src/model/RepeatTemplateDefinition.ts +10 -15
- package/src/model/RootDefinition.ts +6 -12
- package/src/model/SubtreeDefinition.ts +3 -3
- package/src/model/ValueNodeDefinition.ts +2 -3
- package/dist/body/RepeatDefinition.d.ts +0 -16
- package/dist/body/group/RepeatGroupDefinition.d.ts +0 -13
- package/src/body/RepeatDefinition.ts +0 -54
- package/src/body/group/RepeatGroupDefinition.ts +0 -91
package/dist/solid.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { createUniqueId as createUniqueId$1, createSignal,
|
|
1
|
+
import { createUniqueId as createUniqueId$1, createSignal, createComputed, untrack, createRoot, getOwner, runWithOwner, createMemo, on } from 'solid-js';
|
|
2
2
|
|
|
3
3
|
const identity$1 = (value) => value;
|
|
4
4
|
|
|
5
|
+
const XMLNS_NAMESPACE_URI$1 = "http://www.w3.org/2000/xmlns/";
|
|
5
6
|
const JAVAROSA_NAMESPACE_URI$1 = "http://openrosa.org/javarosa";
|
|
6
7
|
const XFORMS_NAMESPACE_URI$1 = "http://www.w3.org/2002/xforms";
|
|
7
8
|
|
|
@@ -34053,7 +34054,50 @@ const normalizeBodyRefNodesetAttributes = (body) => {
|
|
|
34053
34054
|
}
|
|
34054
34055
|
}
|
|
34055
34056
|
};
|
|
34056
|
-
const
|
|
34057
|
+
const normalizeRepeatGroupAttributes = (group, repeat) => {
|
|
34058
|
+
for (const groupAttribute of group.attributes) {
|
|
34059
|
+
const { localName, namespaceURI, nodeName, value } = groupAttribute;
|
|
34060
|
+
if (
|
|
34061
|
+
// Don't propagate namespace declarations (which appear as attributes in
|
|
34062
|
+
// the browser/XML DOM, either named `xmlns` or with an `xmlns` prefix,
|
|
34063
|
+
// always in the XMLNS namespace).
|
|
34064
|
+
namespaceURI === XMLNS_NAMESPACE_URI$1 || // Don't propagate `ref`, it has been normalized as `nodeset` on the
|
|
34065
|
+
// repeat element.
|
|
34066
|
+
localName === "ref" || // TODO: this accommodates tests of this normalization process, where
|
|
34067
|
+
// certain nodes of interest are given an `id` attribute, and looked up
|
|
34068
|
+
// for the purpose of asserting what was normalized about them. It's
|
|
34069
|
+
// unclear if there's a generally expected behavior around the attribute.
|
|
34070
|
+
localName === "id"
|
|
34071
|
+
) {
|
|
34072
|
+
continue;
|
|
34073
|
+
}
|
|
34074
|
+
if (localName === "appearance" && namespaceURI === XFORMS_NAMESPACE_URI$1 && repeat.hasAttribute(localName)) {
|
|
34075
|
+
const ref = group.getAttribute("ref");
|
|
34076
|
+
throw new Error(
|
|
34077
|
+
`Failed to normalize conflicting "appearances" attribute of group/repeat "${ref}"`
|
|
34078
|
+
);
|
|
34079
|
+
}
|
|
34080
|
+
repeat.setAttributeNS(namespaceURI, nodeName, value);
|
|
34081
|
+
}
|
|
34082
|
+
};
|
|
34083
|
+
const normalizeRepeatGroupLabel = (group, repeat) => {
|
|
34084
|
+
const groupLabel = Array.from(group.children).find((child) => {
|
|
34085
|
+
return child.localName === "label";
|
|
34086
|
+
});
|
|
34087
|
+
if (groupLabel == null) {
|
|
34088
|
+
return;
|
|
34089
|
+
}
|
|
34090
|
+
const repeatLabel = groupLabel.cloneNode(true);
|
|
34091
|
+
repeatLabel.setAttribute("form-definition-source", "repeat-group");
|
|
34092
|
+
repeat.prepend(repeatLabel);
|
|
34093
|
+
groupLabel.remove();
|
|
34094
|
+
};
|
|
34095
|
+
const unwrapRepeatGroup = (group, repeat) => {
|
|
34096
|
+
normalizeRepeatGroupAttributes(group, repeat);
|
|
34097
|
+
normalizeRepeatGroupLabel(group, repeat);
|
|
34098
|
+
group.replaceWith(repeat);
|
|
34099
|
+
};
|
|
34100
|
+
const normalizeRepeatGroups = (body) => {
|
|
34057
34101
|
const repeats = body.querySelectorAll("repeat");
|
|
34058
34102
|
for (const repeat of repeats) {
|
|
34059
34103
|
const parent = repeat.parentElement;
|
|
@@ -34068,11 +34112,8 @@ const normalizeRepeatGroups = (xformDocument, body) => {
|
|
|
34068
34112
|
group = parent;
|
|
34069
34113
|
}
|
|
34070
34114
|
}
|
|
34071
|
-
if (group
|
|
34072
|
-
group
|
|
34073
|
-
group.setAttribute("ref", repeatNodeset);
|
|
34074
|
-
repeat.before(group);
|
|
34075
|
-
group.append(repeat);
|
|
34115
|
+
if (group != null) {
|
|
34116
|
+
unwrapRepeatGroup(group, repeat);
|
|
34076
34117
|
}
|
|
34077
34118
|
}
|
|
34078
34119
|
};
|
|
@@ -34090,7 +34131,7 @@ const parseNormalizedXForm = (sourceXML, options) => {
|
|
|
34090
34131
|
normalizedXML = sourceXML;
|
|
34091
34132
|
} else {
|
|
34092
34133
|
normalizeBodyRefNodesetAttributes(body);
|
|
34093
|
-
normalizeRepeatGroups(
|
|
34134
|
+
normalizeRepeatGroups(body);
|
|
34094
34135
|
normalizedXML = html.outerHTML;
|
|
34095
34136
|
}
|
|
34096
34137
|
return {
|
|
@@ -34222,6 +34263,70 @@ class DependencyContext {
|
|
|
34222
34263
|
}
|
|
34223
34264
|
}
|
|
34224
34265
|
|
|
34266
|
+
const XML_XPATH_WHITESPACE_SUBPATTERN = "[\\x20\\x09\\x0D\\x0A]";
|
|
34267
|
+
const XML_XPATH_WHITESPACE_PATTERN = new RegExp(XML_XPATH_WHITESPACE_SUBPATTERN, "g");
|
|
34268
|
+
const XML_XPATH_LEADING_TRAILING_WHITESPACE_PATTERN = new RegExp(
|
|
34269
|
+
`^${XML_XPATH_WHITESPACE_SUBPATTERN}+|${XML_XPATH_WHITESPACE_SUBPATTERN}+$`,
|
|
34270
|
+
"g"
|
|
34271
|
+
);
|
|
34272
|
+
const XPATH_REPEATING_WHITESPACE_PATTERN = new RegExp(
|
|
34273
|
+
`${XML_XPATH_WHITESPACE_SUBPATTERN}{2,}`,
|
|
34274
|
+
"g"
|
|
34275
|
+
);
|
|
34276
|
+
const trimXMLXPathWhitespace = (value) => value.replaceAll(XML_XPATH_LEADING_TRAILING_WHITESPACE_PATTERN, "");
|
|
34277
|
+
const normalizeXMLXPathWhitespace = (value) => trimXMLXPathWhitespace(value).replaceAll(XPATH_REPEATING_WHITESPACE_PATTERN, " ");
|
|
34278
|
+
const xmlXPathWhitespaceSeparatedList = (value, options) => {
|
|
34279
|
+
if (options?.ignoreEmpty && value === "") {
|
|
34280
|
+
return [];
|
|
34281
|
+
}
|
|
34282
|
+
return normalizeXMLXPathWhitespace(value).split(XML_XPATH_WHITESPACE_PATTERN);
|
|
34283
|
+
};
|
|
34284
|
+
|
|
34285
|
+
class TokenListParser {
|
|
34286
|
+
constructor(canonicalTokens, options) {
|
|
34287
|
+
this.canonicalTokens = canonicalTokens;
|
|
34288
|
+
this.aliases = new Map(
|
|
34289
|
+
(options?.aliases ?? []).map(({ fromAlias, toCanonical }) => {
|
|
34290
|
+
return [fromAlias, toCanonical];
|
|
34291
|
+
})
|
|
34292
|
+
);
|
|
34293
|
+
}
|
|
34294
|
+
aliases;
|
|
34295
|
+
parseFrom(element, attributeName) {
|
|
34296
|
+
const serialized = element.getAttribute(attributeName) ?? "";
|
|
34297
|
+
const specified = xmlXPathWhitespaceSeparatedList(serialized, {
|
|
34298
|
+
ignoreEmpty: true
|
|
34299
|
+
});
|
|
34300
|
+
const { aliases } = this;
|
|
34301
|
+
const resolved = specified.flatMap((token) => {
|
|
34302
|
+
const alias = aliases.get(token);
|
|
34303
|
+
if (alias == null) {
|
|
34304
|
+
return token;
|
|
34305
|
+
}
|
|
34306
|
+
return [alias, token];
|
|
34307
|
+
});
|
|
34308
|
+
const tokens = new Set(resolved);
|
|
34309
|
+
return new Proxy(
|
|
34310
|
+
{
|
|
34311
|
+
[Symbol.iterator]() {
|
|
34312
|
+
return resolved.values();
|
|
34313
|
+
}
|
|
34314
|
+
},
|
|
34315
|
+
{
|
|
34316
|
+
get(target, property, receiver) {
|
|
34317
|
+
if (typeof property === "symbol") {
|
|
34318
|
+
return Reflect.get(target, property, receiver);
|
|
34319
|
+
}
|
|
34320
|
+
return tokens.has(property);
|
|
34321
|
+
},
|
|
34322
|
+
set() {
|
|
34323
|
+
return false;
|
|
34324
|
+
}
|
|
34325
|
+
}
|
|
34326
|
+
);
|
|
34327
|
+
}
|
|
34328
|
+
}
|
|
34329
|
+
|
|
34225
34330
|
class BodyElementDefinition extends DependencyContext {
|
|
34226
34331
|
constructor(form, parent, element) {
|
|
34227
34332
|
super();
|
|
@@ -34246,17 +34351,7 @@ class BodyElementDefinition extends DependencyContext {
|
|
|
34246
34351
|
}
|
|
34247
34352
|
}
|
|
34248
34353
|
|
|
34249
|
-
|
|
34250
|
-
static isCompatible() {
|
|
34251
|
-
return true;
|
|
34252
|
-
}
|
|
34253
|
-
category = "UNSUPPORTED";
|
|
34254
|
-
type = "UNSUPPORTED";
|
|
34255
|
-
reference = null;
|
|
34256
|
-
constructor(form, parent, element) {
|
|
34257
|
-
super(form, parent, element);
|
|
34258
|
-
}
|
|
34259
|
-
}
|
|
34354
|
+
const structureElementAppearanceParser = new TokenListParser(["field-list", "table-list"]);
|
|
34260
34355
|
|
|
34261
34356
|
const SUPPORTS_SCOPE_CHILD_SELECTOR = (() => {
|
|
34262
34357
|
const parent = document.createElement("parent");
|
|
@@ -34318,7 +34413,10 @@ const hintLookup = new ScopedElementLookup(":scope > hint", "hint");
|
|
|
34318
34413
|
const itemLookup = new ScopedElementLookup(":scope > item", "item");
|
|
34319
34414
|
const itemsetLookup = new ScopedElementLookup(":scope > itemset[nodeset]", "itemset[nodeset]");
|
|
34320
34415
|
const labelLookup = new ScopedElementLookup(":scope > label", "label");
|
|
34321
|
-
const
|
|
34416
|
+
const repeatGroupLabelLookup = new ScopedElementLookup(
|
|
34417
|
+
':scope > label[form-definition-source="repeat-group"]',
|
|
34418
|
+
'label[form-definition-source="repeat-group"]'
|
|
34419
|
+
);
|
|
34322
34420
|
const valueLookup = new ScopedElementLookup(":scope > value", "value");
|
|
34323
34421
|
const getHintElement = (parent) => {
|
|
34324
34422
|
return hintLookup.getElement(parent);
|
|
@@ -34332,8 +34430,8 @@ const getItemsetElement = (parent) => {
|
|
|
34332
34430
|
const getLabelElement = (parent) => {
|
|
34333
34431
|
return labelLookup.getElement(parent);
|
|
34334
34432
|
};
|
|
34335
|
-
const
|
|
34336
|
-
return
|
|
34433
|
+
const getRepeatGroupLabelElement = (parent) => {
|
|
34434
|
+
return repeatGroupLabelLookup.getElement(parent);
|
|
34337
34435
|
};
|
|
34338
34436
|
const getValueElement = (parent) => {
|
|
34339
34437
|
return valueLookup.getElement(parent);
|
|
@@ -34641,17 +34739,6 @@ class TextElementDefinition extends BodyElementDefinition {
|
|
|
34641
34739
|
}
|
|
34642
34740
|
}
|
|
34643
34741
|
|
|
34644
|
-
class HintDefinition extends TextElementDefinition {
|
|
34645
|
-
static forElement(form, definition) {
|
|
34646
|
-
const hintElement = getHintElement(definition.element);
|
|
34647
|
-
if (hintElement == null) {
|
|
34648
|
-
return null;
|
|
34649
|
-
}
|
|
34650
|
-
return new this(form, definition, hintElement);
|
|
34651
|
-
}
|
|
34652
|
-
type = "hint";
|
|
34653
|
-
}
|
|
34654
|
-
|
|
34655
34742
|
class LabelDefinition extends TextElementDefinition {
|
|
34656
34743
|
static staticDefinition(form, definition) {
|
|
34657
34744
|
const labelElement = getLabelElement(definition.element);
|
|
@@ -34663,6 +34750,13 @@ class LabelDefinition extends TextElementDefinition {
|
|
|
34663
34750
|
static forControl(form, control) {
|
|
34664
34751
|
return this.staticDefinition(form, control);
|
|
34665
34752
|
}
|
|
34753
|
+
static forRepeatGroup(form, repeat) {
|
|
34754
|
+
const repeatGroupLabel = getRepeatGroupLabelElement(repeat.element);
|
|
34755
|
+
if (repeatGroupLabel == null) {
|
|
34756
|
+
return null;
|
|
34757
|
+
}
|
|
34758
|
+
return new this(form, repeat, repeatGroupLabel);
|
|
34759
|
+
}
|
|
34666
34760
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
34667
34761
|
static forGroup(form, group) {
|
|
34668
34762
|
return this.staticDefinition(form, group);
|
|
@@ -34680,6 +34774,68 @@ class LabelDefinition extends TextElementDefinition {
|
|
|
34680
34774
|
type = "label";
|
|
34681
34775
|
}
|
|
34682
34776
|
|
|
34777
|
+
class RepeatElementDefinition extends BodyElementDefinition {
|
|
34778
|
+
static isCompatible(localName) {
|
|
34779
|
+
return localName === "repeat";
|
|
34780
|
+
}
|
|
34781
|
+
category = "structure";
|
|
34782
|
+
type = "repeat";
|
|
34783
|
+
reference;
|
|
34784
|
+
appearances;
|
|
34785
|
+
label;
|
|
34786
|
+
// TODO: this will fall into the growing category of non-`BindExpression`
|
|
34787
|
+
// cases which have roughly the same design story.
|
|
34788
|
+
countExpression;
|
|
34789
|
+
isFixedCount;
|
|
34790
|
+
children;
|
|
34791
|
+
constructor(form, parent, element) {
|
|
34792
|
+
super(form, parent, element);
|
|
34793
|
+
this.label = LabelDefinition.forRepeatGroup(form, this);
|
|
34794
|
+
const reference = element.getAttribute("nodeset");
|
|
34795
|
+
if (reference == null) {
|
|
34796
|
+
throw new Error("Invalid repeat: missing `nodeset` reference");
|
|
34797
|
+
}
|
|
34798
|
+
this.reference = reference;
|
|
34799
|
+
this.appearances = structureElementAppearanceParser.parseFrom(element, "appearance");
|
|
34800
|
+
this.countExpression = element.getAttributeNS(JAVAROSA_NAMESPACE_URI$1, "count");
|
|
34801
|
+
const childElements = Array.from(element.children).filter((childElement) => {
|
|
34802
|
+
const { localName } = childElement;
|
|
34803
|
+
return localName !== "label" && localName !== "group-label";
|
|
34804
|
+
});
|
|
34805
|
+
const children = BodyDefinition.getChildElementDefinitions(form, this, element, childElements);
|
|
34806
|
+
this.children = children;
|
|
34807
|
+
const noAddRemove = element.getAttributeNS(JAVAROSA_NAMESPACE_URI$1, "noAddRemove")?.trim().replaceAll(/\s+/g, "") ?? "false()";
|
|
34808
|
+
this.isFixedCount = noAddRemove === "true()";
|
|
34809
|
+
}
|
|
34810
|
+
toJSON() {
|
|
34811
|
+
const { form, parent, ...rest } = this;
|
|
34812
|
+
return rest;
|
|
34813
|
+
}
|
|
34814
|
+
}
|
|
34815
|
+
|
|
34816
|
+
class UnsupportedBodyElementDefinition extends BodyElementDefinition {
|
|
34817
|
+
static isCompatible() {
|
|
34818
|
+
return true;
|
|
34819
|
+
}
|
|
34820
|
+
category = "UNSUPPORTED";
|
|
34821
|
+
type = "UNSUPPORTED";
|
|
34822
|
+
reference = null;
|
|
34823
|
+
constructor(form, parent, element) {
|
|
34824
|
+
super(form, parent, element);
|
|
34825
|
+
}
|
|
34826
|
+
}
|
|
34827
|
+
|
|
34828
|
+
class HintDefinition extends TextElementDefinition {
|
|
34829
|
+
static forElement(form, definition) {
|
|
34830
|
+
const hintElement = getHintElement(definition.element);
|
|
34831
|
+
if (hintElement == null) {
|
|
34832
|
+
return null;
|
|
34833
|
+
}
|
|
34834
|
+
return new this(form, definition, hintElement);
|
|
34835
|
+
}
|
|
34836
|
+
type = "hint";
|
|
34837
|
+
}
|
|
34838
|
+
|
|
34683
34839
|
class ControlDefinition extends BodyElementDefinition {
|
|
34684
34840
|
category = "control";
|
|
34685
34841
|
reference;
|
|
@@ -34697,13 +34853,84 @@ class ControlDefinition extends BodyElementDefinition {
|
|
|
34697
34853
|
}
|
|
34698
34854
|
}
|
|
34699
34855
|
|
|
34856
|
+
const inputAppearanceParser = new TokenListParser([
|
|
34857
|
+
"multiline",
|
|
34858
|
+
"numbers",
|
|
34859
|
+
"url",
|
|
34860
|
+
"thousand-sep",
|
|
34861
|
+
// date (TODO: data types)
|
|
34862
|
+
"no-calendar",
|
|
34863
|
+
"month-year",
|
|
34864
|
+
"year",
|
|
34865
|
+
// date > calendars
|
|
34866
|
+
"ethiopian",
|
|
34867
|
+
"coptic",
|
|
34868
|
+
"islamic",
|
|
34869
|
+
"bikram-sambat",
|
|
34870
|
+
"myanmar",
|
|
34871
|
+
"persian",
|
|
34872
|
+
// geo (TODO: data types)
|
|
34873
|
+
"placement-map",
|
|
34874
|
+
"maps",
|
|
34875
|
+
// image/media (TODO: move to eventual `<upload>`?)
|
|
34876
|
+
"hidden-answer",
|
|
34877
|
+
"annotate",
|
|
34878
|
+
"draw",
|
|
34879
|
+
"signature",
|
|
34880
|
+
"new-front",
|
|
34881
|
+
"new",
|
|
34882
|
+
"front",
|
|
34883
|
+
// *?
|
|
34884
|
+
"printer",
|
|
34885
|
+
// Note: actual usage uses `printer:...` (like `ex:...`).
|
|
34886
|
+
"masked"
|
|
34887
|
+
]);
|
|
34888
|
+
|
|
34700
34889
|
class InputDefinition extends ControlDefinition {
|
|
34701
34890
|
static isCompatible(localName) {
|
|
34702
34891
|
return localName === "input";
|
|
34703
34892
|
}
|
|
34704
34893
|
type = "input";
|
|
34894
|
+
appearances;
|
|
34895
|
+
constructor(form, parent, element) {
|
|
34896
|
+
super(form, parent, element);
|
|
34897
|
+
this.appearances = inputAppearanceParser.parseFrom(element, "appearance");
|
|
34898
|
+
}
|
|
34705
34899
|
}
|
|
34706
34900
|
|
|
34901
|
+
const selectAppearanceParser = new TokenListParser(
|
|
34902
|
+
[
|
|
34903
|
+
// From XLSForm Docs:
|
|
34904
|
+
"compact",
|
|
34905
|
+
"horizontal",
|
|
34906
|
+
"horizontal-compact",
|
|
34907
|
+
"label",
|
|
34908
|
+
"list-nolabel",
|
|
34909
|
+
"minimal",
|
|
34910
|
+
// From Collect `Appearances.kt`:
|
|
34911
|
+
"columns",
|
|
34912
|
+
"columns-1",
|
|
34913
|
+
"columns-2",
|
|
34914
|
+
"columns-3",
|
|
34915
|
+
"columns-4",
|
|
34916
|
+
"columns-5",
|
|
34917
|
+
// Note: Collect supports arbitrary columns-n. Technically we do too (we parse
|
|
34918
|
+
// out any appearance, not just those we know about). But we'll only include
|
|
34919
|
+
// types/defaults up to 5.
|
|
34920
|
+
"columns-pack",
|
|
34921
|
+
"autocomplete",
|
|
34922
|
+
// TODO: these are `<select1>` only
|
|
34923
|
+
"likert",
|
|
34924
|
+
"quick",
|
|
34925
|
+
"quickcompact",
|
|
34926
|
+
"map"
|
|
34927
|
+
// "quick map"
|
|
34928
|
+
],
|
|
34929
|
+
{
|
|
34930
|
+
aliases: [{ fromAlias: "search", toCanonical: "autocomplete" }]
|
|
34931
|
+
}
|
|
34932
|
+
);
|
|
34933
|
+
|
|
34707
34934
|
class ItemDefinition extends BodyElementDefinition {
|
|
34708
34935
|
constructor(form, parent, element) {
|
|
34709
34936
|
const valueElement = getValueElement(element);
|
|
@@ -34757,7 +34984,11 @@ class ItemsetDefinition extends BodyElementDefinition {
|
|
|
34757
34984
|
}
|
|
34758
34985
|
}
|
|
34759
34986
|
|
|
34760
|
-
const selectLocalNames = /* @__PURE__ */ new Set([
|
|
34987
|
+
const selectLocalNames = /* @__PURE__ */ new Set([
|
|
34988
|
+
/* 'rank', */
|
|
34989
|
+
"select",
|
|
34990
|
+
"select1"
|
|
34991
|
+
]);
|
|
34761
34992
|
const isSelectElement = (element, localName = element.localName) => {
|
|
34762
34993
|
return selectLocalNames.has(localName);
|
|
34763
34994
|
};
|
|
@@ -34770,6 +35001,7 @@ class SelectDefinition extends ControlDefinition {
|
|
|
34770
35001
|
}
|
|
34771
35002
|
type;
|
|
34772
35003
|
element;
|
|
35004
|
+
appearances;
|
|
34773
35005
|
itemset;
|
|
34774
35006
|
items;
|
|
34775
35007
|
constructor(form, parent, element) {
|
|
@@ -34777,8 +35009,9 @@ class SelectDefinition extends ControlDefinition {
|
|
|
34777
35009
|
throw new Error(`Invalid select element: <${element.nodeName}>`);
|
|
34778
35010
|
}
|
|
34779
35011
|
super(form, parent, element);
|
|
34780
|
-
this.element = element;
|
|
34781
35012
|
this.type = element.localName;
|
|
35013
|
+
this.element = element;
|
|
35014
|
+
this.appearances = selectAppearanceParser.parseFrom(element, "appearance");
|
|
34782
35015
|
const itemsetElement = getItemsetElement(element);
|
|
34783
35016
|
const itemElements = getItemElements(element);
|
|
34784
35017
|
if (itemsetElement == null) {
|
|
@@ -34811,22 +35044,16 @@ class UpsertableMap extends Map {
|
|
|
34811
35044
|
}
|
|
34812
35045
|
|
|
34813
35046
|
class BaseGroupDefinition extends BodyElementDefinition {
|
|
35047
|
+
// TODO: does this really accomplish anything? It seems highly unlikely it
|
|
35048
|
+
// has enough performance benefit to outweigh its memory and lookup costs.
|
|
34814
35049
|
static groupTypes = new UpsertableMap();
|
|
34815
35050
|
static getGroupType(localName, element) {
|
|
34816
35051
|
return this.groupTypes.upsert(element, () => {
|
|
34817
35052
|
if (localName !== "group") {
|
|
34818
35053
|
return null;
|
|
34819
35054
|
}
|
|
34820
|
-
|
|
34821
|
-
|
|
34822
|
-
const repeat = getRepeatElement(element);
|
|
34823
|
-
if (repeat == null) {
|
|
34824
|
-
return "logical-group";
|
|
34825
|
-
}
|
|
34826
|
-
if (repeat.getAttribute("nodeset") === ref) {
|
|
34827
|
-
return "repeat-group";
|
|
34828
|
-
}
|
|
34829
|
-
throw new Error("Unexpected <repeat> child of unrelated <group>");
|
|
35055
|
+
if (element.hasAttribute("ref")) {
|
|
35056
|
+
return "logical-group";
|
|
34830
35057
|
}
|
|
34831
35058
|
const label = getLabelElement(element);
|
|
34832
35059
|
if (label == null) {
|
|
@@ -34838,18 +35065,20 @@ class BaseGroupDefinition extends BodyElementDefinition {
|
|
|
34838
35065
|
category = "structure";
|
|
34839
35066
|
children;
|
|
34840
35067
|
reference;
|
|
35068
|
+
appearances;
|
|
34841
35069
|
label;
|
|
34842
35070
|
constructor(form, parent, element, children) {
|
|
34843
35071
|
super(form, parent, element);
|
|
34844
35072
|
this.children = children ?? this.getChildren(element);
|
|
34845
35073
|
this.reference = element.getAttribute("ref");
|
|
35074
|
+
this.appearances = structureElementAppearanceParser.parseFrom(element, "appearance");
|
|
34846
35075
|
this.label = LabelDefinition.forGroup(form, this);
|
|
34847
35076
|
}
|
|
34848
35077
|
getChildren(element) {
|
|
34849
35078
|
const { form } = this;
|
|
34850
35079
|
const children = Array.from(element.children).filter((child) => {
|
|
34851
35080
|
const childName = child.localName;
|
|
34852
|
-
return childName !== "label"
|
|
35081
|
+
return childName !== "label";
|
|
34853
35082
|
});
|
|
34854
35083
|
return BodyDefinition.getChildElementDefinitions(form, this, element, children);
|
|
34855
35084
|
}
|
|
@@ -34878,54 +35107,6 @@ class PresentationGroupDefinition extends BaseGroupDefinition {
|
|
|
34878
35107
|
}
|
|
34879
35108
|
}
|
|
34880
35109
|
|
|
34881
|
-
class RepeatDefinition extends BodyElementDefinition {
|
|
34882
|
-
constructor(form, groupDefinition, element) {
|
|
34883
|
-
super(form, groupDefinition, element);
|
|
34884
|
-
this.groupDefinition = groupDefinition;
|
|
34885
|
-
const reference = element.getAttribute("nodeset");
|
|
34886
|
-
if (reference == null) {
|
|
34887
|
-
throw new Error("Invalid repeat: missing `nodeset` reference");
|
|
34888
|
-
}
|
|
34889
|
-
this.reference = reference;
|
|
34890
|
-
this.countExpression = element.getAttributeNS(JAVAROSA_NAMESPACE_URI$1, "count");
|
|
34891
|
-
this.children = groupDefinition.getChildren(element);
|
|
34892
|
-
const noAddRemove = element.getAttributeNS(JAVAROSA_NAMESPACE_URI$1, "noAddRemove")?.trim().replaceAll(/\s+/g, "") ?? "false()";
|
|
34893
|
-
this.isFixedCount = noAddRemove === "true()";
|
|
34894
|
-
}
|
|
34895
|
-
category = "structure";
|
|
34896
|
-
type = "repeat";
|
|
34897
|
-
reference;
|
|
34898
|
-
// TODO: this will fall into the growing category of non-`BindExpression`
|
|
34899
|
-
// cases which have roughly the same design story.
|
|
34900
|
-
countExpression;
|
|
34901
|
-
isFixedCount;
|
|
34902
|
-
children;
|
|
34903
|
-
toJSON() {
|
|
34904
|
-
const { form, groupDefinition, parent, ...rest } = this;
|
|
34905
|
-
return rest;
|
|
34906
|
-
}
|
|
34907
|
-
}
|
|
34908
|
-
|
|
34909
|
-
class RepeatGroupDefinition extends BaseGroupDefinition {
|
|
34910
|
-
static isCompatible(localName, element) {
|
|
34911
|
-
return this.getGroupType(localName, element) === "repeat-group";
|
|
34912
|
-
}
|
|
34913
|
-
type = "repeat-group";
|
|
34914
|
-
repeat;
|
|
34915
|
-
get repeatChildren() {
|
|
34916
|
-
return this.repeat.children;
|
|
34917
|
-
}
|
|
34918
|
-
constructor(form, parent, element) {
|
|
34919
|
-
const repeat = getRepeatElement(element);
|
|
34920
|
-
if (repeat == null) {
|
|
34921
|
-
throw new Error("Invalid repeat-group");
|
|
34922
|
-
}
|
|
34923
|
-
super(form, parent, element);
|
|
34924
|
-
const repeatDefinition = new RepeatDefinition(form, this, repeat);
|
|
34925
|
-
this.repeat = repeatDefinition;
|
|
34926
|
-
}
|
|
34927
|
-
}
|
|
34928
|
-
|
|
34929
35110
|
class StructuralGroupDefinition extends BaseGroupDefinition {
|
|
34930
35111
|
static isCompatible(localName, element) {
|
|
34931
35112
|
return this.getGroupType(localName, element) === "structural-group";
|
|
@@ -34934,7 +35115,7 @@ class StructuralGroupDefinition extends BaseGroupDefinition {
|
|
|
34934
35115
|
}
|
|
34935
35116
|
|
|
34936
35117
|
const BodyElementDefinitionConstructors = [
|
|
34937
|
-
|
|
35118
|
+
RepeatElementDefinition,
|
|
34938
35119
|
LogicalGroupDefinition,
|
|
34939
35120
|
PresentationGroupDefinition,
|
|
34940
35121
|
StructuralGroupDefinition,
|
|
@@ -34949,12 +35130,12 @@ class BodyElementMap extends Map {
|
|
|
34949
35130
|
mapElementsByReference(elements) {
|
|
34950
35131
|
for (const element of elements) {
|
|
34951
35132
|
const { reference } = element;
|
|
34952
|
-
if (element instanceof
|
|
35133
|
+
if (element instanceof RepeatElementDefinition) {
|
|
34953
35134
|
if (reference == null) {
|
|
34954
|
-
throw new Error("Missing reference for repeat
|
|
35135
|
+
throw new Error("Missing reference for repeat");
|
|
34955
35136
|
}
|
|
34956
35137
|
this.set(reference, element);
|
|
34957
|
-
this.mapElementsByReference(element.
|
|
35138
|
+
this.mapElementsByReference(element.children);
|
|
34958
35139
|
}
|
|
34959
35140
|
if (element instanceof LogicalGroupDefinition || element instanceof PresentationGroupDefinition || element instanceof StructuralGroupDefinition) {
|
|
34960
35141
|
if (reference != null) {
|
|
@@ -34980,6 +35161,10 @@ class BodyElementMap extends Map {
|
|
|
34980
35161
|
return Object.fromEntries(this.entries());
|
|
34981
35162
|
}
|
|
34982
35163
|
}
|
|
35164
|
+
const bodyClassParser = new TokenListParser([
|
|
35165
|
+
"pages"
|
|
35166
|
+
/*, 'theme-grid' */
|
|
35167
|
+
]);
|
|
34983
35168
|
class BodyDefinition extends DependencyContext {
|
|
34984
35169
|
constructor(form) {
|
|
34985
35170
|
super();
|
|
@@ -34987,6 +35172,7 @@ class BodyDefinition extends DependencyContext {
|
|
|
34987
35172
|
const { body: element } = form.xformDOM;
|
|
34988
35173
|
this.reference = form.rootReference;
|
|
34989
35174
|
this.element = element;
|
|
35175
|
+
this.classes = bodyClassParser.parseFrom(element, "class");
|
|
34990
35176
|
this.elements = BodyDefinition.getChildElementDefinitions(form, this, element);
|
|
34991
35177
|
this.elementsByReference = new BodyElementMap(this.elements);
|
|
34992
35178
|
}
|
|
@@ -35002,6 +35188,23 @@ class BodyDefinition extends DependencyContext {
|
|
|
35002
35188
|
});
|
|
35003
35189
|
}
|
|
35004
35190
|
element;
|
|
35191
|
+
/**
|
|
35192
|
+
* @todo this class is already an oddity in that it's **like** an element
|
|
35193
|
+
* definition, but it isn't one itself. Adding this property here emphasizes
|
|
35194
|
+
* that awkwardness. It also extends the applicable scope where instances of
|
|
35195
|
+
* this class are accessed. While it's still ephemeral, it's anticipated that
|
|
35196
|
+
* this extension might cause some disomfort. If so, the most plausible
|
|
35197
|
+
* alternative is an additional refactor to:
|
|
35198
|
+
*
|
|
35199
|
+
* 1. Introduce a `BodyElementDefinition` sublass for `<h:body>`.
|
|
35200
|
+
* 2. Disambiguate the respective names of those, in some reasonable way.
|
|
35201
|
+
* 3. Add a layer of indirection between this class and that new body element
|
|
35202
|
+
* definition's class.
|
|
35203
|
+
* 4. At that point, we may as well prioritize the little bit of grunt work to
|
|
35204
|
+
* pass the `BodyDefinition` instance by reference rather than assigning it
|
|
35205
|
+
* to anything.
|
|
35206
|
+
*/
|
|
35207
|
+
classes;
|
|
35005
35208
|
elements;
|
|
35006
35209
|
elementsByReference;
|
|
35007
35210
|
// DependencyContext
|
|
@@ -35010,13 +35213,6 @@ class BodyDefinition extends DependencyContext {
|
|
|
35010
35213
|
getBodyElement(reference) {
|
|
35011
35214
|
return this.elementsByReference.get(reference) ?? null;
|
|
35012
35215
|
}
|
|
35013
|
-
getRepeatGroup(reference) {
|
|
35014
|
-
const element = this.getBodyElement(reference);
|
|
35015
|
-
if (element?.type === "repeat-group") {
|
|
35016
|
-
return element;
|
|
35017
|
-
}
|
|
35018
|
-
return null;
|
|
35019
|
-
}
|
|
35020
35216
|
toJSON() {
|
|
35021
35217
|
const { form, ...rest } = this;
|
|
35022
35218
|
return rest;
|
|
@@ -35249,17 +35445,11 @@ class DescendentNodeDefinition {
|
|
|
35249
35445
|
}
|
|
35250
35446
|
|
|
35251
35447
|
class RepeatInstanceDefinition extends DescendentNodeDefinition {
|
|
35252
|
-
constructor(
|
|
35253
|
-
const {
|
|
35254
|
-
|
|
35255
|
-
bodyElement: repeatGroupBodyElement,
|
|
35256
|
-
parent: repeatSequenceParent,
|
|
35257
|
-
root
|
|
35258
|
-
} = sequence;
|
|
35259
|
-
super(repeatSequenceParent, bind, repeatGroupBodyElement.repeat);
|
|
35260
|
-
this.sequence = sequence;
|
|
35448
|
+
constructor(range, node) {
|
|
35449
|
+
const { bind, bodyElement, parent, root } = range;
|
|
35450
|
+
super(parent, bind, bodyElement);
|
|
35261
35451
|
this.node = node;
|
|
35262
|
-
this.nodeName =
|
|
35452
|
+
this.nodeName = range.nodeName;
|
|
35263
35453
|
this.children = root.buildSubtree(this);
|
|
35264
35454
|
}
|
|
35265
35455
|
type = "repeat-instance";
|
|
@@ -35268,7 +35458,7 @@ class RepeatInstanceDefinition extends DescendentNodeDefinition {
|
|
|
35268
35458
|
instances = null;
|
|
35269
35459
|
defaultValue = null;
|
|
35270
35460
|
toJSON() {
|
|
35271
|
-
const { bind, bodyElement, parent, root,
|
|
35461
|
+
const { bind, bodyElement, parent, root, ...rest } = this;
|
|
35272
35462
|
return rest;
|
|
35273
35463
|
}
|
|
35274
35464
|
}
|
|
@@ -35307,15 +35497,9 @@ const splitInstanceNodes = (modelNodes) => {
|
|
|
35307
35497
|
return [template, ...modelNodes];
|
|
35308
35498
|
};
|
|
35309
35499
|
class RepeatTemplateDefinition extends DescendentNodeDefinition {
|
|
35310
|
-
constructor(
|
|
35311
|
-
const {
|
|
35312
|
-
|
|
35313
|
-
bodyElement: repeatGroupBodyElement,
|
|
35314
|
-
parent: repeatSequenceParent,
|
|
35315
|
-
root
|
|
35316
|
-
} = sequence;
|
|
35317
|
-
super(repeatSequenceParent, bind, repeatGroupBodyElement.repeat);
|
|
35318
|
-
this.sequence = sequence;
|
|
35500
|
+
constructor(range, templateNode) {
|
|
35501
|
+
const { bind, bodyElement, parent, root } = range;
|
|
35502
|
+
super(parent, bind, bodyElement);
|
|
35319
35503
|
this.templateNode = templateNode;
|
|
35320
35504
|
const node = templateNode.cloneNode(true);
|
|
35321
35505
|
node.removeAttributeNS(JAVAROSA_NAMESPACE_URI$1, "template");
|
|
@@ -35323,14 +35507,14 @@ class RepeatTemplateDefinition extends DescendentNodeDefinition {
|
|
|
35323
35507
|
this.nodeName = node.localName;
|
|
35324
35508
|
this.children = root.buildSubtree(this);
|
|
35325
35509
|
}
|
|
35326
|
-
static parseModelNodes(
|
|
35327
|
-
const { bind } =
|
|
35510
|
+
static parseModelNodes(range, modelNodes) {
|
|
35511
|
+
const { bind } = range;
|
|
35328
35512
|
let template = repeatTemplates.get(bind);
|
|
35329
35513
|
let instanceNodes;
|
|
35330
35514
|
if (template == null) {
|
|
35331
35515
|
const [templateNode, ...rest] = splitInstanceNodes(modelNodes);
|
|
35332
35516
|
instanceNodes = rest;
|
|
35333
|
-
template = new this(
|
|
35517
|
+
template = new this(range, templateNode);
|
|
35334
35518
|
} else {
|
|
35335
35519
|
const duplicateTemplate = modelNodes.find(
|
|
35336
35520
|
(node) => node.hasAttributeNS(JAVAROSA_NAMESPACE_URI$1, "template")
|
|
@@ -35352,12 +35536,12 @@ class RepeatTemplateDefinition extends DescendentNodeDefinition {
|
|
|
35352
35536
|
instances = null;
|
|
35353
35537
|
defaultValue = null;
|
|
35354
35538
|
toJSON() {
|
|
35355
|
-
const { bind, bodyElement, parent, root,
|
|
35539
|
+
const { bind, bodyElement, parent, root, ...rest } = this;
|
|
35356
35540
|
return rest;
|
|
35357
35541
|
}
|
|
35358
35542
|
}
|
|
35359
35543
|
|
|
35360
|
-
class
|
|
35544
|
+
class RepeatRangeDefinition extends DescendentNodeDefinition {
|
|
35361
35545
|
// TODO: if an implicit template is derived from an instance in a form
|
|
35362
35546
|
// definition, should its default values (if any) be cleared? Probably!
|
|
35363
35547
|
static createTemplateElement(instanceElement) {
|
|
@@ -35366,7 +35550,7 @@ class RepeatSequenceDefinition extends DescendentNodeDefinition {
|
|
|
35366
35550
|
static createInstanceElement(templateElement) {
|
|
35367
35551
|
return templateElement.cloneNode(true);
|
|
35368
35552
|
}
|
|
35369
|
-
type = "repeat-
|
|
35553
|
+
type = "repeat-range";
|
|
35370
35554
|
template;
|
|
35371
35555
|
children = null;
|
|
35372
35556
|
instances;
|
|
@@ -35390,7 +35574,7 @@ class RepeatSequenceDefinition extends DescendentNodeDefinition {
|
|
|
35390
35574
|
|
|
35391
35575
|
class SubtreeDefinition extends DescendentNodeDefinition {
|
|
35392
35576
|
constructor(parent, bind, bodyElement, node) {
|
|
35393
|
-
if (bodyElement != null && (bodyElement.category !== "structure" || bodyElement.type === "repeat
|
|
35577
|
+
if (bodyElement != null && (bodyElement.category !== "structure" || bodyElement.type === "repeat")) {
|
|
35394
35578
|
throw new Error(`Unexpected body element for nodeset ${bind.nodeset}`);
|
|
35395
35579
|
}
|
|
35396
35580
|
super(parent, bind, bodyElement);
|
|
@@ -35432,9 +35616,10 @@ class ValueNodeDefinition extends DescendentNodeDefinition {
|
|
|
35432
35616
|
}
|
|
35433
35617
|
|
|
35434
35618
|
class RootDefinition {
|
|
35435
|
-
constructor(form, model) {
|
|
35619
|
+
constructor(form, model, classes) {
|
|
35436
35620
|
this.form = form;
|
|
35437
35621
|
this.model = model;
|
|
35622
|
+
this.classes = classes;
|
|
35438
35623
|
const { primaryInstanceRoot } = form.xformDOM;
|
|
35439
35624
|
const { localName: rootNodeName } = primaryInstanceRoot;
|
|
35440
35625
|
this.nodeName = rootNodeName;
|
|
@@ -35483,13 +35668,8 @@ class RootDefinition {
|
|
|
35483
35668
|
const bind = binds.getOrCreateBindDefinition(nodeset);
|
|
35484
35669
|
const bodyElement = body.getBodyElement(nodeset);
|
|
35485
35670
|
const [firstChild, ...restChildren] = children;
|
|
35486
|
-
|
|
35487
|
-
|
|
35488
|
-
const repeatDefinition = bodyElement.repeat;
|
|
35489
|
-
if (repeatDefinition == null) {
|
|
35490
|
-
throw 'TODO: this is why I have hesitated to pick an "is repeat" predicate direction';
|
|
35491
|
-
}
|
|
35492
|
-
return new RepeatSequenceDefinition(parent, bind, repeatGroup, children);
|
|
35671
|
+
if (bodyElement?.type === "repeat") {
|
|
35672
|
+
return new RepeatRangeDefinition(parent, bind, bodyElement, children);
|
|
35493
35673
|
}
|
|
35494
35674
|
if (restChildren.length) {
|
|
35495
35675
|
throw new Error(`Unexpected: multiple elements for non-repeat nodeset: ${nodeset}`);
|
|
@@ -35512,7 +35692,7 @@ class ModelDefinition {
|
|
|
35512
35692
|
constructor(form) {
|
|
35513
35693
|
this.form = form;
|
|
35514
35694
|
this.binds = ModelBindMap.fromModel(this);
|
|
35515
|
-
this.root = new RootDefinition(form, this);
|
|
35695
|
+
this.root = new RootDefinition(form, this, form.body.classes);
|
|
35516
35696
|
}
|
|
35517
35697
|
binds;
|
|
35518
35698
|
root;
|
|
@@ -35642,11 +35822,26 @@ const createUniqueId = (() => {
|
|
|
35642
35822
|
|
|
35643
35823
|
const createChildrenState = (parent) => {
|
|
35644
35824
|
return parent.scope.runTask(() => {
|
|
35645
|
-
const
|
|
35646
|
-
const [getChildren,
|
|
35647
|
-
const
|
|
35648
|
-
|
|
35649
|
-
|
|
35825
|
+
const baseState = createSignal([]);
|
|
35826
|
+
const [getChildren, baseSetChildren] = baseState;
|
|
35827
|
+
const ids = createSignal([]);
|
|
35828
|
+
const [childIds, setChildIds] = ids;
|
|
35829
|
+
const setChildren = (valueOrSetterCallback) => {
|
|
35830
|
+
let setterCallback;
|
|
35831
|
+
if (typeof valueOrSetterCallback === "function") {
|
|
35832
|
+
setterCallback = valueOrSetterCallback;
|
|
35833
|
+
} else {
|
|
35834
|
+
setterCallback = (_) => valueOrSetterCallback;
|
|
35835
|
+
}
|
|
35836
|
+
return baseSetChildren((prev) => {
|
|
35837
|
+
const result = setterCallback(prev);
|
|
35838
|
+
setChildIds(() => {
|
|
35839
|
+
return result.map((child) => child.nodeId);
|
|
35840
|
+
});
|
|
35841
|
+
return result;
|
|
35842
|
+
});
|
|
35843
|
+
};
|
|
35844
|
+
const children = [getChildren, setChildren];
|
|
35650
35845
|
return {
|
|
35651
35846
|
children,
|
|
35652
35847
|
getChildren,
|
|
@@ -35656,13 +35851,13 @@ const createChildrenState = (parent) => {
|
|
|
35656
35851
|
});
|
|
35657
35852
|
};
|
|
35658
35853
|
|
|
35659
|
-
const materializeCurrentStateChildren = (currentState, childrenState) => {
|
|
35854
|
+
const materializeCurrentStateChildren = (scope, currentState, childrenState) => {
|
|
35660
35855
|
const baseState = currentState;
|
|
35661
35856
|
const proxyTarget = baseState;
|
|
35662
35857
|
return new Proxy(proxyTarget, {
|
|
35663
35858
|
get(_, key) {
|
|
35664
35859
|
if (key === "children") {
|
|
35665
|
-
currentState.children;
|
|
35860
|
+
scope.runTask(() => currentState.children);
|
|
35666
35861
|
const children = childrenState.getChildren();
|
|
35667
35862
|
return children;
|
|
35668
35863
|
}
|
|
@@ -35865,104 +36060,59 @@ const declareNodeID = (id) => {
|
|
|
35865
36060
|
};
|
|
35866
36061
|
|
|
35867
36062
|
class InstanceNode {
|
|
35868
|
-
constructor(engineConfig, parent, definition) {
|
|
36063
|
+
constructor(engineConfig, parent, definition, options) {
|
|
35869
36064
|
this.engineConfig = engineConfig;
|
|
35870
36065
|
this.parent = parent;
|
|
35871
36066
|
this.definition = definition;
|
|
36067
|
+
this.computeReference = options?.computeReference ?? this.computeChildStepReference;
|
|
35872
36068
|
this.scope = createReactiveScope();
|
|
35873
36069
|
this.engineConfig = engineConfig;
|
|
35874
36070
|
this.nodeId = declareNodeID(engineConfig.createUniqueId());
|
|
35875
36071
|
this.definition = definition;
|
|
35876
|
-
const checkStateInitialized = () => this.engineState != null;
|
|
35877
|
-
const [isStateInitialized, setStateInitialized] = createSignal(checkStateInitialized());
|
|
35878
|
-
this.isStateInitialized = isStateInitialized;
|
|
35879
|
-
queueMicrotask(() => {
|
|
35880
|
-
if (checkStateInitialized()) {
|
|
35881
|
-
setStateInitialized(true);
|
|
35882
|
-
} else {
|
|
35883
|
-
throw new Error("Node state was never initialized");
|
|
35884
|
-
}
|
|
35885
|
-
});
|
|
35886
|
-
}
|
|
35887
|
-
isStateInitialized;
|
|
35888
|
-
/**
|
|
35889
|
-
* Provides a generalized mechanism for accessing a reactive state value
|
|
35890
|
-
* during a node's construction, while {@link engineState} is still being
|
|
35891
|
-
* defined and thus isn't assigned.
|
|
35892
|
-
*
|
|
35893
|
-
* The fallback value specified in {@link options} will be returned on access
|
|
35894
|
-
* until {@link isStateInitialized} returns true. This ensures:
|
|
35895
|
-
*
|
|
35896
|
-
* - a value of the expected type will be available
|
|
35897
|
-
* - any read access will become reactive to the actual state, once it has
|
|
35898
|
-
* been initialized and {@link engineState} is assigned
|
|
35899
|
-
*
|
|
35900
|
-
* @todo This is one among several chicken/egg problems encountered trying to
|
|
35901
|
-
* support state initialization in which some aspects of the state derive from
|
|
35902
|
-
* other aspects of it. It would be nice to dispense with this entirely. But
|
|
35903
|
-
* if it must persist, we should also consider replacing the method with a
|
|
35904
|
-
* direct accessor once state initialization completes, so the initialized
|
|
35905
|
-
* check is only called until it becomes impertinent.
|
|
35906
|
-
*/
|
|
35907
|
-
getInitializedState(key, options) {
|
|
35908
|
-
if (this.isStateInitialized()) {
|
|
35909
|
-
return this.engineState[key];
|
|
35910
|
-
}
|
|
35911
|
-
return options.uninitializedFallback;
|
|
35912
|
-
}
|
|
35913
|
-
/**
|
|
35914
|
-
* @package Exposed on every node type to facilitate inheritance, as well as
|
|
35915
|
-
* conditional behavior for value nodes.
|
|
35916
|
-
*/
|
|
35917
|
-
get isReadonly() {
|
|
35918
|
-
return this.getInitializedState("readonly", {
|
|
35919
|
-
uninitializedFallback: false
|
|
35920
|
-
});
|
|
35921
|
-
}
|
|
35922
|
-
/**
|
|
35923
|
-
* @package Exposed on every node type to facilitate inheritance, as well as
|
|
35924
|
-
* conditional behavior for value nodes.
|
|
35925
|
-
*/
|
|
35926
|
-
get isRelevant() {
|
|
35927
|
-
return this.getInitializedState("relevant", {
|
|
35928
|
-
uninitializedFallback: true
|
|
35929
|
-
});
|
|
35930
36072
|
}
|
|
35931
36073
|
// BaseNode: identity
|
|
35932
36074
|
nodeId;
|
|
35933
36075
|
// EvaluationContext *and* Subscribable: node-specific
|
|
35934
36076
|
scope;
|
|
36077
|
+
computeReference;
|
|
36078
|
+
computeChildStepReference = (parent, definition) => {
|
|
36079
|
+
if (parent == null) {
|
|
36080
|
+
throw new Error(
|
|
36081
|
+
"Cannot compute child step reference of node without parent (was this called from `Root`?)"
|
|
36082
|
+
);
|
|
36083
|
+
}
|
|
36084
|
+
return `${parent.contextReference()}/${definition.nodeName}`;
|
|
36085
|
+
};
|
|
35935
36086
|
// EvaluationContext: node-specific
|
|
35936
|
-
|
|
36087
|
+
contextReference = () => {
|
|
35937
36088
|
return this.computeReference(this.parent, this.definition);
|
|
35938
|
-
}
|
|
35939
|
-
|
|
36089
|
+
};
|
|
36090
|
+
getNodesByReference(visited, dependencyReference) {
|
|
35940
36091
|
if (visited.has(this)) {
|
|
35941
|
-
return
|
|
36092
|
+
return [];
|
|
35942
36093
|
}
|
|
35943
36094
|
visited.add(this);
|
|
35944
36095
|
const { nodeset } = this.definition;
|
|
35945
36096
|
if (dependencyReference === nodeset) {
|
|
35946
|
-
|
|
36097
|
+
if (this.nodeType === "repeat-instance") {
|
|
36098
|
+
return [this.parent];
|
|
36099
|
+
}
|
|
36100
|
+
return [this];
|
|
35947
36101
|
}
|
|
35948
36102
|
if (dependencyReference.startsWith(`${nodeset}/`) || dependencyReference.startsWith(`${nodeset}[`)) {
|
|
35949
|
-
|
|
35950
|
-
|
|
35951
|
-
|
|
35952
|
-
}
|
|
35953
|
-
for (const child of children) {
|
|
35954
|
-
const dependency = child.getNodeByReference(visited, dependencyReference);
|
|
35955
|
-
if (dependency != null) {
|
|
35956
|
-
return dependency;
|
|
35957
|
-
}
|
|
35958
|
-
}
|
|
36103
|
+
return this.getChildren().flatMap((child) => {
|
|
36104
|
+
return child.getNodesByReference(visited, dependencyReference);
|
|
36105
|
+
});
|
|
35959
36106
|
}
|
|
35960
|
-
return this.parent?.
|
|
36107
|
+
return this.parent?.getNodesByReference(visited, dependencyReference) ?? [];
|
|
35961
36108
|
}
|
|
35962
36109
|
// EvaluationContext: node-relative
|
|
35963
|
-
|
|
35964
|
-
|
|
35965
|
-
|
|
36110
|
+
getSubscribableDependenciesByReference(reference) {
|
|
36111
|
+
if (this.nodeType === "root") {
|
|
36112
|
+
const visited = /* @__PURE__ */ new WeakSet();
|
|
36113
|
+
return this.getNodesByReference(visited, reference);
|
|
36114
|
+
}
|
|
36115
|
+
return this.root.getSubscribableDependenciesByReference(reference);
|
|
35966
36116
|
}
|
|
35967
36117
|
// SubscribableDependency
|
|
35968
36118
|
/**
|
|
@@ -36054,7 +36204,7 @@ const createComputedExpression = (context, dependentExpression) => {
|
|
|
36054
36204
|
}
|
|
36055
36205
|
const getReferencedDependencies = createMemo(() => {
|
|
36056
36206
|
return dependencyReferences.flatMap((reference) => {
|
|
36057
|
-
return context.
|
|
36207
|
+
return context.getSubscribableDependenciesByReference(reference) ?? [];
|
|
36058
36208
|
});
|
|
36059
36209
|
});
|
|
36060
36210
|
let getDependencies;
|
|
@@ -36145,42 +36295,45 @@ const createNodeLabel = (context, definition) => {
|
|
|
36145
36295
|
};
|
|
36146
36296
|
|
|
36147
36297
|
class DescendantNode extends InstanceNode {
|
|
36148
|
-
constructor(parent, definition) {
|
|
36149
|
-
super(parent.engineConfig, parent, definition);
|
|
36298
|
+
constructor(parent, definition, options) {
|
|
36299
|
+
super(parent.engineConfig, parent, definition, options);
|
|
36150
36300
|
this.parent = parent;
|
|
36151
36301
|
this.definition = definition;
|
|
36152
36302
|
const { evaluator, root } = parent;
|
|
36153
36303
|
this.root = root;
|
|
36154
36304
|
this.evaluator = evaluator;
|
|
36155
36305
|
this.contextNode = this.initializeContextNode(parent.contextNode, definition.nodeName);
|
|
36156
|
-
|
|
36306
|
+
const { readonly, relevant, required } = definition.bind;
|
|
36307
|
+
this.isSelfReadonly = createComputedExpression(this, readonly);
|
|
36308
|
+
this.isSelfRelevant = createComputedExpression(this, relevant);
|
|
36309
|
+
this.isRequired = createComputedExpression(this, required);
|
|
36310
|
+
}
|
|
36311
|
+
hasReadonlyAncestor = () => {
|
|
36312
|
+
const { parent } = this;
|
|
36313
|
+
return parent.hasReadonlyAncestor() || parent.isReadonly();
|
|
36314
|
+
};
|
|
36315
|
+
isSelfReadonly;
|
|
36316
|
+
isReadonly = () => {
|
|
36317
|
+
if (this.hasReadonlyAncestor()) {
|
|
36318
|
+
return true;
|
|
36319
|
+
}
|
|
36320
|
+
return this.isSelfReadonly();
|
|
36321
|
+
};
|
|
36322
|
+
hasNonRelevantAncestor = () => {
|
|
36323
|
+
const { parent } = this;
|
|
36324
|
+
return parent.hasNonRelevantAncestor() || !parent.isRelevant();
|
|
36325
|
+
};
|
|
36326
|
+
isSelfRelevant;
|
|
36327
|
+
isRelevant = () => {
|
|
36328
|
+
if (this.hasNonRelevantAncestor()) {
|
|
36329
|
+
return false;
|
|
36330
|
+
}
|
|
36331
|
+
return this.isSelfRelevant();
|
|
36332
|
+
};
|
|
36333
|
+
isRequired;
|
|
36157
36334
|
root;
|
|
36158
36335
|
evaluator;
|
|
36159
36336
|
contextNode;
|
|
36160
|
-
computeChildStepReference(parent) {
|
|
36161
|
-
return `${parent.contextReference}/${this.definition.nodeName}`;
|
|
36162
|
-
}
|
|
36163
|
-
buildSharedStateSpec(parent, definition) {
|
|
36164
|
-
return this.scope.runTask(() => {
|
|
36165
|
-
const reference = createMemo(() => this.contextReference);
|
|
36166
|
-
const { bind } = definition;
|
|
36167
|
-
const selfReadonly = createComputedExpression(this, bind.readonly);
|
|
36168
|
-
const readonly = createMemo(() => {
|
|
36169
|
-
return parent.isReadonly || selfReadonly();
|
|
36170
|
-
});
|
|
36171
|
-
const selfRelevant = createComputedExpression(this, bind.relevant);
|
|
36172
|
-
const relevant = createMemo(() => {
|
|
36173
|
-
return parent.isRelevant && selfRelevant();
|
|
36174
|
-
});
|
|
36175
|
-
const required = createComputedExpression(this, bind.required);
|
|
36176
|
-
return {
|
|
36177
|
-
reference,
|
|
36178
|
-
readonly,
|
|
36179
|
-
relevant,
|
|
36180
|
-
required
|
|
36181
|
-
};
|
|
36182
|
-
});
|
|
36183
|
-
}
|
|
36184
36337
|
createContextNode(parentContextNode, nodeName) {
|
|
36185
36338
|
return parentContextNode.ownerDocument.createElement(nodeName);
|
|
36186
36339
|
}
|
|
@@ -36243,16 +36396,21 @@ class Group extends DescendantNode {
|
|
|
36243
36396
|
state;
|
|
36244
36397
|
engineState;
|
|
36245
36398
|
// GroupNode
|
|
36246
|
-
currentState;
|
|
36247
36399
|
nodeType = "group";
|
|
36400
|
+
appearances;
|
|
36401
|
+
currentState;
|
|
36248
36402
|
constructor(parent, definition) {
|
|
36249
36403
|
super(parent, definition);
|
|
36404
|
+
this.appearances = definition.bodyElement.appearances;
|
|
36250
36405
|
const childrenState = createChildrenState(this);
|
|
36251
36406
|
this.childrenState = childrenState;
|
|
36252
36407
|
const state = createSharedNodeState(
|
|
36253
36408
|
this.scope,
|
|
36254
36409
|
{
|
|
36255
|
-
|
|
36410
|
+
reference: this.contextReference,
|
|
36411
|
+
readonly: this.isReadonly,
|
|
36412
|
+
relevant: this.isRelevant,
|
|
36413
|
+
required: this.isRequired,
|
|
36256
36414
|
label: createNodeLabel(this, definition),
|
|
36257
36415
|
hint: null,
|
|
36258
36416
|
children: childrenState.childIds,
|
|
@@ -36265,12 +36423,13 @@ class Group extends DescendantNode {
|
|
|
36265
36423
|
);
|
|
36266
36424
|
this.state = state;
|
|
36267
36425
|
this.engineState = state.engineState;
|
|
36268
|
-
this.currentState = materializeCurrentStateChildren(
|
|
36426
|
+
this.currentState = materializeCurrentStateChildren(
|
|
36427
|
+
this.scope,
|
|
36428
|
+
state.currentState,
|
|
36429
|
+
childrenState
|
|
36430
|
+
);
|
|
36269
36431
|
childrenState.setChildren(buildChildren(this));
|
|
36270
36432
|
}
|
|
36271
|
-
computeReference(parent) {
|
|
36272
|
-
return this.computeChildStepReference(parent);
|
|
36273
|
-
}
|
|
36274
36433
|
getChildren() {
|
|
36275
36434
|
return this.childrenState.getChildren();
|
|
36276
36435
|
}
|
|
@@ -36295,20 +36454,30 @@ const insertAtIndex = (currentValues, insertionIndex, newValue) => {
|
|
|
36295
36454
|
|
|
36296
36455
|
class RepeatInstance extends DescendantNode {
|
|
36297
36456
|
constructor(parent, definition, options) {
|
|
36298
|
-
super(parent, definition);
|
|
36299
|
-
this.parent = parent;
|
|
36300
|
-
const childrenState = createChildrenState(this);
|
|
36301
|
-
this.childrenState = childrenState;
|
|
36302
|
-
options.precedingPrimaryInstanceNode.after(this.contextNode);
|
|
36303
36457
|
const { precedingInstance } = options;
|
|
36304
36458
|
const precedingIndex = precedingInstance?.currentIndex ?? (() => -1);
|
|
36305
36459
|
const initialIndex = precedingIndex() + 1;
|
|
36306
36460
|
const [currentIndex, setCurrentIndex] = createSignal(initialIndex);
|
|
36461
|
+
super(parent, definition, {
|
|
36462
|
+
computeReference: () => {
|
|
36463
|
+
const currentPosition = currentIndex() + 1;
|
|
36464
|
+
return `${parent.contextReference()}[${currentPosition}]`;
|
|
36465
|
+
}
|
|
36466
|
+
});
|
|
36467
|
+
this.parent = parent;
|
|
36468
|
+
this.appearances = definition.bodyElement.appearances;
|
|
36469
|
+
const childrenState = createChildrenState(this);
|
|
36470
|
+
this.childrenState = childrenState;
|
|
36471
|
+
options.precedingPrimaryInstanceNode.after(this.contextNode);
|
|
36307
36472
|
this.currentIndex = currentIndex;
|
|
36308
36473
|
const state = createSharedNodeState(
|
|
36309
36474
|
this.scope,
|
|
36310
36475
|
{
|
|
36311
|
-
|
|
36476
|
+
reference: this.contextReference,
|
|
36477
|
+
readonly: this.isReadonly,
|
|
36478
|
+
relevant: this.isRelevant,
|
|
36479
|
+
required: this.isRequired,
|
|
36480
|
+
// TODO: only-child <group><label>
|
|
36312
36481
|
label: createNodeLabel(this, definition),
|
|
36313
36482
|
hint: null,
|
|
36314
36483
|
children: childrenState.childIds,
|
|
@@ -36321,7 +36490,11 @@ class RepeatInstance extends DescendantNode {
|
|
|
36321
36490
|
);
|
|
36322
36491
|
this.state = state;
|
|
36323
36492
|
this.engineState = state.engineState;
|
|
36324
|
-
this.currentState = materializeCurrentStateChildren(
|
|
36493
|
+
this.currentState = materializeCurrentStateChildren(
|
|
36494
|
+
this.scope,
|
|
36495
|
+
state.currentState,
|
|
36496
|
+
childrenState
|
|
36497
|
+
);
|
|
36325
36498
|
this.scope.runTask(() => {
|
|
36326
36499
|
const computeCurrentIndex = parent.getInstanceIndex.bind(parent, this);
|
|
36327
36500
|
createComputed(on(computeCurrentIndex, setCurrentIndex, { defer: true }));
|
|
@@ -36333,13 +36506,29 @@ class RepeatInstance extends DescendantNode {
|
|
|
36333
36506
|
// InstanceNode
|
|
36334
36507
|
state;
|
|
36335
36508
|
engineState;
|
|
36509
|
+
/**
|
|
36510
|
+
* A repeat instance can inherit non-relevance, just like any other node. That
|
|
36511
|
+
* inheritance is derived from the repeat instance's parent node in the
|
|
36512
|
+
* primary instance XML/DOM tree (and would be semantically expected to do so
|
|
36513
|
+
* even if we move away from that implementation detail).
|
|
36514
|
+
*
|
|
36515
|
+
* Since {@link RepeatInstance.parent} is a {@link RepeatRange}, which is a
|
|
36516
|
+
* runtime data model fiction that does not exist in that hierarchy, we pass
|
|
36517
|
+
* this call through, allowing the {@link RepeatRange} to check the actual
|
|
36518
|
+
* primary instance parent node's relevance state.
|
|
36519
|
+
*
|
|
36520
|
+
* @todo Should we apply similar reasoning in {@link hasReadonlyAncestor}?
|
|
36521
|
+
*/
|
|
36522
|
+
hasNonRelevantAncestor = () => {
|
|
36523
|
+
return this.parent.hasNonRelevantAncestor();
|
|
36524
|
+
};
|
|
36336
36525
|
// RepeatInstanceNode
|
|
36337
36526
|
nodeType = "repeat-instance";
|
|
36527
|
+
/**
|
|
36528
|
+
* @see {@link RepeatRange.appearances}
|
|
36529
|
+
*/
|
|
36530
|
+
appearances;
|
|
36338
36531
|
currentState;
|
|
36339
|
-
computeReference(parent) {
|
|
36340
|
-
const currentPosition = this.currentIndex() + 1;
|
|
36341
|
-
return `${parent.contextReference}[${currentPosition}]`;
|
|
36342
|
-
}
|
|
36343
36532
|
initializeContextNode(parentContextNode, nodeName) {
|
|
36344
36533
|
return this.createContextNode(parentContextNode, nodeName);
|
|
36345
36534
|
}
|
|
@@ -36403,17 +36592,118 @@ class RepeatRange extends DescendantNode {
|
|
|
36403
36592
|
// InstanceNode
|
|
36404
36593
|
state;
|
|
36405
36594
|
engineState;
|
|
36595
|
+
emptyRangeEvaluationContext;
|
|
36596
|
+
/**
|
|
36597
|
+
* @see {@link isSelfRelevant}
|
|
36598
|
+
*/
|
|
36599
|
+
isEmptyRangeSelfRelevant;
|
|
36600
|
+
/**
|
|
36601
|
+
* A repeat range does not exist in the primary instance tree. A `relevant`
|
|
36602
|
+
* expression applies to each {@link RepeatInstance} child of the repeat
|
|
36603
|
+
* range. Determining whether a repeat range itself "is relevant" isn't a
|
|
36604
|
+
* concept the spec addresses, but it may be used by clients to determine
|
|
36605
|
+
* whether to allow interaction with the range (e.g. by adding a repeat
|
|
36606
|
+
* instance, or presenting the range's label when empty).
|
|
36607
|
+
*
|
|
36608
|
+
* As a naive first pass, it seems like the heuristic for this should be:
|
|
36609
|
+
*
|
|
36610
|
+
* 1. Does the repeat range have any repeat instance children?
|
|
36611
|
+
*
|
|
36612
|
+
* - If yes, go to 2.
|
|
36613
|
+
* - If no, go to 3.
|
|
36614
|
+
*
|
|
36615
|
+
* 2. Does one or more of those children return `true` for the node's
|
|
36616
|
+
* `relevant` expression (i.e. is the repeat instance "self relevant")?
|
|
36617
|
+
*
|
|
36618
|
+
* 3. Does the relevant expression return `true` for the repeat range itself
|
|
36619
|
+
* (where, at least for now, the context of that evaluation would be the
|
|
36620
|
+
* repeat range's {@link anchorNode} to ensure correct relative expressions
|
|
36621
|
+
* resolve correctly)?
|
|
36622
|
+
*
|
|
36623
|
+
* @todo While (3) is proactively implemented, there isn't presently a test
|
|
36624
|
+
* exercising it. It felt best for now to surface this for discussion in
|
|
36625
|
+
* review to validate that it's going in the right direction.
|
|
36626
|
+
*
|
|
36627
|
+
* @todo While (2) **is actually tested**, the tests currently in place behave
|
|
36628
|
+
* the same way with only the logic for (3), regardless of whether the repeat
|
|
36629
|
+
* range actually has any repeat instance children. It's unclear (a) if that's
|
|
36630
|
+
* a preferable simplification and (b) how that might affect performance (in
|
|
36631
|
+
* theory it could vary depending on form structure and runtime state).
|
|
36632
|
+
*/
|
|
36633
|
+
isSelfRelevant = () => {
|
|
36634
|
+
const instances = this.childrenState.getChildren();
|
|
36635
|
+
if (instances.length > 0) {
|
|
36636
|
+
return instances.some((instance) => instance.isSelfRelevant());
|
|
36637
|
+
}
|
|
36638
|
+
return this.isEmptyRangeSelfRelevant();
|
|
36639
|
+
};
|
|
36406
36640
|
// RepeatRangeNode
|
|
36407
36641
|
nodeType = "repeat-range";
|
|
36642
|
+
/**
|
|
36643
|
+
* @todo RepeatRange*, RepeatInstance* (and RepeatTemplate*) all share the
|
|
36644
|
+
* same body element, and thus all share the same definition `bodyElement`. As
|
|
36645
|
+
* such, they also all share the same `appearances`. At time of writing,
|
|
36646
|
+
* `web-forms` (Vue UI package) treats a `RepeatRangeNode`...
|
|
36647
|
+
*
|
|
36648
|
+
* - ... as a group, if the node has a label (i.e.
|
|
36649
|
+
* `<group><label/><repeat/></group>`)
|
|
36650
|
+
* - ... effectively as a fragment containing only its instances, otherwise
|
|
36651
|
+
*
|
|
36652
|
+
* We now collapse `<group><repeat>` into `<repeat>`, and no longer treat
|
|
36653
|
+
* "repeat group" as a concept (after parsing). According to the spec, these
|
|
36654
|
+
* appearances **are supposed to** come from that "repeat group" in the form
|
|
36655
|
+
* definition. In practice, many forms do define appearances directly on a
|
|
36656
|
+
* repeat element. The engine currently produces an error if both are defined
|
|
36657
|
+
* simultaneously, but otherwise makes no distinction between appearances in
|
|
36658
|
+
* these form definition shapes:
|
|
36659
|
+
*
|
|
36660
|
+
* ```xml
|
|
36661
|
+
* <group ref="/data/rep1" appearance="...">
|
|
36662
|
+
* <repeat nodeset="/data/rep1"/>
|
|
36663
|
+
* </group>
|
|
36664
|
+
*
|
|
36665
|
+
* <group ref="/data/rep1">
|
|
36666
|
+
* <repeat nodeset="/data/rep1"/ appearance="...">
|
|
36667
|
+
* </group>
|
|
36668
|
+
*
|
|
36669
|
+
* <repeat nodeset="/data/rep1"/ appearance="...">
|
|
36670
|
+
* ```
|
|
36671
|
+
*
|
|
36672
|
+
* All of the above creates considerable ambiguity about where "repeat
|
|
36673
|
+
* appearances" should apply, under which circumstances.
|
|
36674
|
+
*/
|
|
36675
|
+
appearances;
|
|
36408
36676
|
currentState;
|
|
36409
36677
|
constructor(parent, definition) {
|
|
36410
36678
|
super(parent, definition);
|
|
36679
|
+
this.appearances = definition.bodyElement.appearances;
|
|
36411
36680
|
const childrenState = createChildrenState(this);
|
|
36412
36681
|
this.childrenState = childrenState;
|
|
36682
|
+
this.anchorNode = this.contextNode.ownerDocument.createComment(
|
|
36683
|
+
`Begin repeat range: ${definition.nodeset}`
|
|
36684
|
+
);
|
|
36685
|
+
this.contextNode.append(this.anchorNode);
|
|
36686
|
+
this.emptyRangeEvaluationContext = {
|
|
36687
|
+
scope: this.scope,
|
|
36688
|
+
evaluator: this.evaluator,
|
|
36689
|
+
root: this.root,
|
|
36690
|
+
contextReference: this.contextReference,
|
|
36691
|
+
contextNode: this.anchorNode,
|
|
36692
|
+
getSubscribableDependenciesByReference: (reference) => {
|
|
36693
|
+
return this.getSubscribableDependenciesByReference(reference);
|
|
36694
|
+
}
|
|
36695
|
+
};
|
|
36696
|
+
this.isEmptyRangeSelfRelevant = createComputedExpression(
|
|
36697
|
+
this.emptyRangeEvaluationContext,
|
|
36698
|
+
definition.bind.relevant
|
|
36699
|
+
);
|
|
36413
36700
|
const state = createSharedNodeState(
|
|
36414
36701
|
this.scope,
|
|
36415
36702
|
{
|
|
36416
|
-
|
|
36703
|
+
reference: this.contextReference,
|
|
36704
|
+
readonly: this.isReadonly,
|
|
36705
|
+
relevant: this.isRelevant,
|
|
36706
|
+
required: this.isRequired,
|
|
36417
36707
|
label: createNodeLabel(this, definition),
|
|
36418
36708
|
hint: null,
|
|
36419
36709
|
children: childrenState.childIds,
|
|
@@ -36424,13 +36714,13 @@ class RepeatRange extends DescendantNode {
|
|
|
36424
36714
|
clientStateFactory: this.engineConfig.stateFactory
|
|
36425
36715
|
}
|
|
36426
36716
|
);
|
|
36427
|
-
this.anchorNode = this.contextNode.ownerDocument.createComment(
|
|
36428
|
-
`Begin repeat range: ${definition.nodeset}`
|
|
36429
|
-
);
|
|
36430
|
-
this.contextNode.append(this.anchorNode);
|
|
36431
36717
|
this.state = state;
|
|
36432
36718
|
this.engineState = state.engineState;
|
|
36433
|
-
this.currentState = materializeCurrentStateChildren(
|
|
36719
|
+
this.currentState = materializeCurrentStateChildren(
|
|
36720
|
+
this.scope,
|
|
36721
|
+
state.currentState,
|
|
36722
|
+
childrenState
|
|
36723
|
+
);
|
|
36434
36724
|
definition.instances.forEach((instanceDefinition, index) => {
|
|
36435
36725
|
const afterIndex = index - 1;
|
|
36436
36726
|
this.addInstances(afterIndex, 1, instanceDefinition);
|
|
@@ -36442,9 +36732,6 @@ class RepeatRange extends DescendantNode {
|
|
|
36442
36732
|
initializeContextNode(parentContextNode) {
|
|
36443
36733
|
return parentContextNode;
|
|
36444
36734
|
}
|
|
36445
|
-
computeReference(parent) {
|
|
36446
|
-
return this.computeChildStepReference(parent);
|
|
36447
|
-
}
|
|
36448
36735
|
getInstanceIndex(instance) {
|
|
36449
36736
|
return this.engineState.children.indexOf(instance.nodeId);
|
|
36450
36737
|
}
|
|
@@ -36516,25 +36803,6 @@ class RepeatRange extends DescendantNode {
|
|
|
36516
36803
|
}
|
|
36517
36804
|
}
|
|
36518
36805
|
|
|
36519
|
-
const XML_XPATH_WHITESPACE_SUBPATTERN = "[\\x20\\x09\\x0D\\x0A]";
|
|
36520
|
-
const XML_XPATH_WHITESPACE_PATTERN = new RegExp(XML_XPATH_WHITESPACE_SUBPATTERN, "g");
|
|
36521
|
-
const XML_XPATH_LEADING_TRAILING_WHITESPACE_PATTERN = new RegExp(
|
|
36522
|
-
`^${XML_XPATH_WHITESPACE_SUBPATTERN}+|${XML_XPATH_WHITESPACE_SUBPATTERN}+$`,
|
|
36523
|
-
"g"
|
|
36524
|
-
);
|
|
36525
|
-
const XPATH_REPEATING_WHITESPACE_PATTERN = new RegExp(
|
|
36526
|
-
`${XML_XPATH_WHITESPACE_SUBPATTERN}{2,}`,
|
|
36527
|
-
"g"
|
|
36528
|
-
);
|
|
36529
|
-
const trimXMLXPathWhitespace = (value) => value.replaceAll(XML_XPATH_LEADING_TRAILING_WHITESPACE_PATTERN, "");
|
|
36530
|
-
const normalizeXMLXPathWhitespace = (value) => trimXMLXPathWhitespace(value).replaceAll(XPATH_REPEATING_WHITESPACE_PATTERN, " ");
|
|
36531
|
-
const xmlXPathWhitespaceSeparatedList = (value, options) => {
|
|
36532
|
-
if (value === "") {
|
|
36533
|
-
return [];
|
|
36534
|
-
}
|
|
36535
|
-
return normalizeXMLXPathWhitespace(value).split(XML_XPATH_WHITESPACE_PATTERN);
|
|
36536
|
-
};
|
|
36537
|
-
|
|
36538
36806
|
const createSelectItemLabel = (context, definition) => {
|
|
36539
36807
|
const { label, value } = definition;
|
|
36540
36808
|
return createTextRange(context, "label", label, {
|
|
@@ -36563,15 +36831,14 @@ class ItemsetItemEvaluationContext {
|
|
|
36563
36831
|
this.scope = selectField.scope;
|
|
36564
36832
|
this.evaluator = selectField.evaluator;
|
|
36565
36833
|
this.root = selectField.root;
|
|
36834
|
+
this.contextReference = selectField.contextReference;
|
|
36566
36835
|
}
|
|
36567
36836
|
scope;
|
|
36568
36837
|
evaluator;
|
|
36569
36838
|
root;
|
|
36570
|
-
|
|
36571
|
-
|
|
36572
|
-
|
|
36573
|
-
getSubscribableDependencyByReference(reference) {
|
|
36574
|
-
return this.selectField.getSubscribableDependencyByReference(reference);
|
|
36839
|
+
contextReference;
|
|
36840
|
+
getSubscribableDependenciesByReference(reference) {
|
|
36841
|
+
return this.selectField.getSubscribableDependenciesByReference(reference);
|
|
36575
36842
|
}
|
|
36576
36843
|
}
|
|
36577
36844
|
const createSelectItemsetItemLabel = (context, definition, itemValue) => {
|
|
@@ -36635,7 +36902,7 @@ const createPrimaryInstanceValueState = (context, options) => {
|
|
|
36635
36902
|
const initialValue = initialValueSource === "PRIMARY_INSTANCE" ? contextNode.textContent ?? defaultValue : defaultValue;
|
|
36636
36903
|
const persistedValueState = createSignal(
|
|
36637
36904
|
{
|
|
36638
|
-
isRelevant: context.isRelevant,
|
|
36905
|
+
isRelevant: context.isRelevant(),
|
|
36639
36906
|
value: initialValue
|
|
36640
36907
|
},
|
|
36641
36908
|
{
|
|
@@ -36652,7 +36919,7 @@ const createPrimaryInstanceValueState = (context, options) => {
|
|
|
36652
36919
|
);
|
|
36653
36920
|
const [persistedValue, setValueForPersistence] = persistedValueState;
|
|
36654
36921
|
createComputed(() => {
|
|
36655
|
-
const isRelevant = context.isRelevant;
|
|
36922
|
+
const isRelevant = context.isRelevant();
|
|
36656
36923
|
setValueForPersistence((persisted) => {
|
|
36657
36924
|
return {
|
|
36658
36925
|
isRelevant,
|
|
@@ -36675,7 +36942,7 @@ const createPrimaryInstanceValueState = (context, options) => {
|
|
|
36675
36942
|
});
|
|
36676
36943
|
const setPrimaryInstanceValue = (value) => {
|
|
36677
36944
|
const persisted = setValueForPersistence({
|
|
36678
|
-
isRelevant: context.isRelevant,
|
|
36945
|
+
isRelevant: context.isRelevant(),
|
|
36679
36946
|
value
|
|
36680
36947
|
});
|
|
36681
36948
|
return persisted.value;
|
|
@@ -36704,8 +36971,8 @@ const guardDownstreamReadonlyWrites = (context, baseState) => {
|
|
|
36704
36971
|
}
|
|
36705
36972
|
const [getValue, baseSetValue] = baseState;
|
|
36706
36973
|
const setValue = (value) => {
|
|
36707
|
-
if (context.isReadonly) {
|
|
36708
|
-
const reference = untrack(() => context.contextReference);
|
|
36974
|
+
if (context.isReadonly()) {
|
|
36975
|
+
const reference = untrack(() => context.contextReference());
|
|
36709
36976
|
throw new Error(`Cannot write to readonly field: ${reference}`);
|
|
36710
36977
|
}
|
|
36711
36978
|
return baseSetValue(value);
|
|
@@ -36716,7 +36983,7 @@ const createCalculation = (context, setValue, calculateDefinition) => {
|
|
|
36716
36983
|
context.scope.runTask(() => {
|
|
36717
36984
|
const calculate = createComputedExpression(context, calculateDefinition);
|
|
36718
36985
|
createComputed(() => {
|
|
36719
|
-
if (context.isRelevant) {
|
|
36986
|
+
if (context.isRelevant()) {
|
|
36720
36987
|
const calculated = calculate();
|
|
36721
36988
|
const value = context.decodeValue(calculated);
|
|
36722
36989
|
setValue(value);
|
|
@@ -36749,6 +37016,7 @@ class SelectField extends DescendantNode {
|
|
|
36749
37016
|
engineState;
|
|
36750
37017
|
// SelectNode
|
|
36751
37018
|
nodeType = "select";
|
|
37019
|
+
appearances;
|
|
36752
37020
|
currentState;
|
|
36753
37021
|
// ValueContext
|
|
36754
37022
|
encodeValue = (runtimeValue) => {
|
|
@@ -36757,7 +37025,9 @@ class SelectField extends DescendantNode {
|
|
|
36757
37025
|
};
|
|
36758
37026
|
decodeValue = (instanceValue) => {
|
|
36759
37027
|
return this.scope.runTask(() => {
|
|
36760
|
-
const values = xmlXPathWhitespaceSeparatedList(instanceValue
|
|
37028
|
+
const values = xmlXPathWhitespaceSeparatedList(instanceValue, {
|
|
37029
|
+
ignoreEmpty: true
|
|
37030
|
+
});
|
|
36761
37031
|
const items = this.getSelectItemsByValue();
|
|
36762
37032
|
return values.map((value) => {
|
|
36763
37033
|
return items.get(value);
|
|
@@ -36769,13 +37039,17 @@ class SelectField extends DescendantNode {
|
|
|
36769
37039
|
getValueOptions;
|
|
36770
37040
|
constructor(parent, definition) {
|
|
36771
37041
|
super(parent, definition);
|
|
37042
|
+
this.appearances = definition.bodyElement.appearances;
|
|
36772
37043
|
this.selectExclusive = definition.bodyElement.type === "select1";
|
|
36773
37044
|
const valueOptions = createSelectItems(this);
|
|
36774
37045
|
this.getValueOptions = valueOptions;
|
|
36775
37046
|
const state = createSharedNodeState(
|
|
36776
37047
|
this.scope,
|
|
36777
37048
|
{
|
|
36778
|
-
|
|
37049
|
+
reference: this.contextReference,
|
|
37050
|
+
readonly: this.isReadonly,
|
|
37051
|
+
relevant: this.isRelevant,
|
|
37052
|
+
required: this.isRequired,
|
|
36779
37053
|
label: createNodeLabel(this, definition),
|
|
36780
37054
|
hint: createFieldHint(this, definition),
|
|
36781
37055
|
children: null,
|
|
@@ -36797,9 +37071,6 @@ class SelectField extends DescendantNode {
|
|
|
36797
37071
|
})
|
|
36798
37072
|
);
|
|
36799
37073
|
}
|
|
36800
|
-
computeReference(parent) {
|
|
36801
|
-
return this.computeChildStepReference(parent);
|
|
36802
|
-
}
|
|
36803
37074
|
updateSelectedItemValues(values) {
|
|
36804
37075
|
const itemsByValue = untrack(() => this.getSelectItemsByValue());
|
|
36805
37076
|
const items = values.flatMap((value) => {
|
|
@@ -36862,16 +37133,21 @@ class StringField extends DescendantNode {
|
|
|
36862
37133
|
engineState;
|
|
36863
37134
|
// StringNode
|
|
36864
37135
|
nodeType = "string";
|
|
37136
|
+
appearances;
|
|
36865
37137
|
currentState;
|
|
36866
37138
|
// ValueContext
|
|
36867
37139
|
encodeValue = identity$1;
|
|
36868
37140
|
decodeValue = identity$1;
|
|
36869
37141
|
constructor(parent, definition) {
|
|
36870
37142
|
super(parent, definition);
|
|
37143
|
+
this.appearances = definition.bodyElement?.appearances ?? null;
|
|
36871
37144
|
const state = createSharedNodeState(
|
|
36872
37145
|
this.scope,
|
|
36873
37146
|
{
|
|
36874
|
-
|
|
37147
|
+
reference: this.contextReference,
|
|
37148
|
+
readonly: this.isReadonly,
|
|
37149
|
+
relevant: this.isRelevant,
|
|
37150
|
+
required: this.isRequired,
|
|
36875
37151
|
label: createNodeLabel(this, definition),
|
|
36876
37152
|
hint: createFieldHint(this, definition),
|
|
36877
37153
|
children: null,
|
|
@@ -36886,9 +37162,6 @@ class StringField extends DescendantNode {
|
|
|
36886
37162
|
this.engineState = state.engineState;
|
|
36887
37163
|
this.currentState = state.currentState;
|
|
36888
37164
|
}
|
|
36889
|
-
computeReference(parent) {
|
|
36890
|
-
return this.computeChildStepReference(parent);
|
|
36891
|
-
}
|
|
36892
37165
|
// InstanceNode
|
|
36893
37166
|
getChildren() {
|
|
36894
37167
|
return [];
|
|
@@ -36907,6 +37180,7 @@ class Subtree extends DescendantNode {
|
|
|
36907
37180
|
engineState;
|
|
36908
37181
|
// SubtreeNode
|
|
36909
37182
|
nodeType = "subtree";
|
|
37183
|
+
appearances = null;
|
|
36910
37184
|
currentState;
|
|
36911
37185
|
constructor(parent, definition) {
|
|
36912
37186
|
super(parent, definition);
|
|
@@ -36915,7 +37189,10 @@ class Subtree extends DescendantNode {
|
|
|
36915
37189
|
const state = createSharedNodeState(
|
|
36916
37190
|
this.scope,
|
|
36917
37191
|
{
|
|
36918
|
-
|
|
37192
|
+
reference: this.contextReference,
|
|
37193
|
+
readonly: this.isReadonly,
|
|
37194
|
+
relevant: this.isRelevant,
|
|
37195
|
+
required: this.isRequired,
|
|
36919
37196
|
label: null,
|
|
36920
37197
|
hint: null,
|
|
36921
37198
|
children: childrenState.childIds,
|
|
@@ -36928,12 +37205,13 @@ class Subtree extends DescendantNode {
|
|
|
36928
37205
|
);
|
|
36929
37206
|
this.state = state;
|
|
36930
37207
|
this.engineState = state.engineState;
|
|
36931
|
-
this.currentState = materializeCurrentStateChildren(
|
|
37208
|
+
this.currentState = materializeCurrentStateChildren(
|
|
37209
|
+
this.scope,
|
|
37210
|
+
state.currentState,
|
|
37211
|
+
childrenState
|
|
37212
|
+
);
|
|
36932
37213
|
childrenState.setChildren(buildChildren(this));
|
|
36933
37214
|
}
|
|
36934
|
-
computeReference(parent) {
|
|
36935
|
-
return this.computeChildStepReference(parent);
|
|
36936
|
-
}
|
|
36937
37215
|
getChildren() {
|
|
36938
37216
|
return this.childrenState.getChildren();
|
|
36939
37217
|
}
|
|
@@ -36952,14 +37230,20 @@ const buildChildren = (parent) => {
|
|
|
36952
37230
|
}
|
|
36953
37231
|
return new Group(parent, child);
|
|
36954
37232
|
}
|
|
36955
|
-
case "repeat-
|
|
37233
|
+
case "repeat-range": {
|
|
36956
37234
|
return new RepeatRange(parent, child);
|
|
36957
37235
|
}
|
|
36958
37236
|
case "value-node": {
|
|
36959
|
-
|
|
36960
|
-
|
|
37237
|
+
switch (child.bodyElement?.type) {
|
|
37238
|
+
case "select":
|
|
37239
|
+
case "select1":
|
|
37240
|
+
return new SelectField(parent, child);
|
|
37241
|
+
case "input":
|
|
37242
|
+
case void 0:
|
|
37243
|
+
return new StringField(parent, child);
|
|
37244
|
+
default:
|
|
37245
|
+
throw new UnreachableError(child.bodyElement);
|
|
36961
37246
|
}
|
|
36962
|
-
return new StringField(parent, child);
|
|
36963
37247
|
}
|
|
36964
37248
|
default: {
|
|
36965
37249
|
throw new UnreachableError(child);
|
|
@@ -36998,27 +37282,24 @@ const getInitialLanguageState = (translations) => {
|
|
|
36998
37282
|
};
|
|
36999
37283
|
};
|
|
37000
37284
|
class Root extends InstanceNode {
|
|
37001
|
-
static async initialize(xformDOM, definition, engineConfig) {
|
|
37002
|
-
const instance = new Root(xformDOM, definition, engineConfig);
|
|
37003
|
-
await instance.formStateInitialized();
|
|
37004
|
-
return instance;
|
|
37005
|
-
}
|
|
37006
37285
|
childrenState;
|
|
37007
37286
|
// InstanceNode
|
|
37287
|
+
hasReadonlyAncestor = () => false;
|
|
37288
|
+
isReadonly = () => false;
|
|
37289
|
+
hasNonRelevantAncestor = () => false;
|
|
37290
|
+
isRelevant = () => true;
|
|
37008
37291
|
state;
|
|
37009
37292
|
engineState;
|
|
37010
37293
|
// RootNode
|
|
37011
37294
|
nodeType = "root";
|
|
37295
|
+
appearances = null;
|
|
37296
|
+
classes;
|
|
37012
37297
|
currentState;
|
|
37013
37298
|
instanceDOM;
|
|
37014
37299
|
// BaseNode
|
|
37015
37300
|
root = this;
|
|
37016
37301
|
// EvaluationContext
|
|
37017
37302
|
evaluator;
|
|
37018
|
-
rootReference;
|
|
37019
|
-
get contextReference() {
|
|
37020
|
-
return this.rootReference;
|
|
37021
|
-
}
|
|
37022
37303
|
contextNode;
|
|
37023
37304
|
// RootNode
|
|
37024
37305
|
parent = null;
|
|
@@ -37028,11 +37309,13 @@ class Root extends InstanceNode {
|
|
|
37028
37309
|
return this.engineState.activeLanguage;
|
|
37029
37310
|
}
|
|
37030
37311
|
constructor(xformDOM, definition, engineConfig) {
|
|
37031
|
-
|
|
37312
|
+
const reference = definition.nodeset;
|
|
37313
|
+
super(engineConfig, null, definition, {
|
|
37314
|
+
computeReference: () => reference
|
|
37315
|
+
});
|
|
37316
|
+
this.classes = definition.classes;
|
|
37032
37317
|
const childrenState = createChildrenState(this);
|
|
37033
37318
|
this.childrenState = childrenState;
|
|
37034
|
-
const reference = definition.nodeset;
|
|
37035
|
-
this.rootReference = reference;
|
|
37036
37319
|
const instanceDOM = xformDOM.createInstance();
|
|
37037
37320
|
const evaluator = instanceDOM.primaryInstanceEvaluator;
|
|
37038
37321
|
const { translations } = evaluator;
|
|
@@ -37057,7 +37340,11 @@ class Root extends InstanceNode {
|
|
|
37057
37340
|
);
|
|
37058
37341
|
this.state = state;
|
|
37059
37342
|
this.engineState = state.engineState;
|
|
37060
|
-
this.currentState = materializeCurrentStateChildren(
|
|
37343
|
+
this.currentState = materializeCurrentStateChildren(
|
|
37344
|
+
this.scope,
|
|
37345
|
+
state.currentState,
|
|
37346
|
+
childrenState
|
|
37347
|
+
);
|
|
37061
37348
|
const contextNode = instanceDOM.xformDocument.createElement(definition.nodeName);
|
|
37062
37349
|
instanceDOM.primaryInstanceRoot.replaceWith(contextNode);
|
|
37063
37350
|
this.evaluator = evaluator;
|
|
@@ -37066,37 +37353,6 @@ class Root extends InstanceNode {
|
|
|
37066
37353
|
this.languages = languages;
|
|
37067
37354
|
childrenState.setChildren(buildChildren(this));
|
|
37068
37355
|
}
|
|
37069
|
-
/**
|
|
37070
|
-
* Waits until form state is fully initialized.
|
|
37071
|
-
*
|
|
37072
|
-
* As much as possible, all instance state computations are implemented so
|
|
37073
|
-
* that they complete synchronously.
|
|
37074
|
-
*
|
|
37075
|
-
* There is currently one exception: because instance nodes may form
|
|
37076
|
-
* computation dependencies into their descendants as well as their ancestors,
|
|
37077
|
-
* there is an allowance **during form initialization only** to account for
|
|
37078
|
-
* this chicken/egg scenario. Note that this allowance is intentionally,
|
|
37079
|
-
* strictly limited: if form state initialization is not resolved within a
|
|
37080
|
-
* single microtask tick we throw/reject.
|
|
37081
|
-
*
|
|
37082
|
-
* All subsequent computations are always performed synchronously (and we will
|
|
37083
|
-
* use tests to validate this, by utilizing the synchronously returned `Root`
|
|
37084
|
-
* state from client-facing write interfaces).
|
|
37085
|
-
*/
|
|
37086
|
-
async formStateInitialized() {
|
|
37087
|
-
await new Promise((resolve) => {
|
|
37088
|
-
queueMicrotask(resolve);
|
|
37089
|
-
});
|
|
37090
|
-
if (!this.isStateInitialized()) {
|
|
37091
|
-
throw new Error(
|
|
37092
|
-
"Form state initialization failed to complete in a single frame. Has some aspect of reactive computation been made asynchronous by mistake?"
|
|
37093
|
-
);
|
|
37094
|
-
}
|
|
37095
|
-
}
|
|
37096
|
-
// InstanceNode
|
|
37097
|
-
computeReference(_parent, definition) {
|
|
37098
|
-
return definition.nodeset;
|
|
37099
|
-
}
|
|
37100
37356
|
getChildren() {
|
|
37101
37357
|
return this.childrenState.getChildren();
|
|
37102
37358
|
}
|
|
@@ -37130,7 +37386,7 @@ const initializeForm$1 = async (input, options = {}) => {
|
|
|
37130
37386
|
const engineConfig = buildInstanceConfig(options.config);
|
|
37131
37387
|
const sourceXML = await retrieveSourceXMLResource(input, engineConfig);
|
|
37132
37388
|
const form = new XFormDefinition(sourceXML);
|
|
37133
|
-
return Root
|
|
37389
|
+
return new Root(form.xformDOM, form.model.root, engineConfig);
|
|
37134
37390
|
};
|
|
37135
37391
|
|
|
37136
37392
|
const initializeForm = initializeForm$1;
|