@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/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const identity$1 = (value) => value;
|
|
2
2
|
|
|
3
|
+
const XMLNS_NAMESPACE_URI$1 = "http://www.w3.org/2000/xmlns/";
|
|
3
4
|
const JAVAROSA_NAMESPACE_URI$1 = "http://openrosa.org/javarosa";
|
|
4
5
|
const XFORMS_NAMESPACE_URI$1 = "http://www.w3.org/2002/xforms";
|
|
5
6
|
|
|
@@ -34051,7 +34052,50 @@ const normalizeBodyRefNodesetAttributes = (body) => {
|
|
|
34051
34052
|
}
|
|
34052
34053
|
}
|
|
34053
34054
|
};
|
|
34054
|
-
const
|
|
34055
|
+
const normalizeRepeatGroupAttributes = (group, repeat) => {
|
|
34056
|
+
for (const groupAttribute of group.attributes) {
|
|
34057
|
+
const { localName, namespaceURI, nodeName, value } = groupAttribute;
|
|
34058
|
+
if (
|
|
34059
|
+
// Don't propagate namespace declarations (which appear as attributes in
|
|
34060
|
+
// the browser/XML DOM, either named `xmlns` or with an `xmlns` prefix,
|
|
34061
|
+
// always in the XMLNS namespace).
|
|
34062
|
+
namespaceURI === XMLNS_NAMESPACE_URI$1 || // Don't propagate `ref`, it has been normalized as `nodeset` on the
|
|
34063
|
+
// repeat element.
|
|
34064
|
+
localName === "ref" || // TODO: this accommodates tests of this normalization process, where
|
|
34065
|
+
// certain nodes of interest are given an `id` attribute, and looked up
|
|
34066
|
+
// for the purpose of asserting what was normalized about them. It's
|
|
34067
|
+
// unclear if there's a generally expected behavior around the attribute.
|
|
34068
|
+
localName === "id"
|
|
34069
|
+
) {
|
|
34070
|
+
continue;
|
|
34071
|
+
}
|
|
34072
|
+
if (localName === "appearance" && namespaceURI === XFORMS_NAMESPACE_URI$1 && repeat.hasAttribute(localName)) {
|
|
34073
|
+
const ref = group.getAttribute("ref");
|
|
34074
|
+
throw new Error(
|
|
34075
|
+
`Failed to normalize conflicting "appearances" attribute of group/repeat "${ref}"`
|
|
34076
|
+
);
|
|
34077
|
+
}
|
|
34078
|
+
repeat.setAttributeNS(namespaceURI, nodeName, value);
|
|
34079
|
+
}
|
|
34080
|
+
};
|
|
34081
|
+
const normalizeRepeatGroupLabel = (group, repeat) => {
|
|
34082
|
+
const groupLabel = Array.from(group.children).find((child) => {
|
|
34083
|
+
return child.localName === "label";
|
|
34084
|
+
});
|
|
34085
|
+
if (groupLabel == null) {
|
|
34086
|
+
return;
|
|
34087
|
+
}
|
|
34088
|
+
const repeatLabel = groupLabel.cloneNode(true);
|
|
34089
|
+
repeatLabel.setAttribute("form-definition-source", "repeat-group");
|
|
34090
|
+
repeat.prepend(repeatLabel);
|
|
34091
|
+
groupLabel.remove();
|
|
34092
|
+
};
|
|
34093
|
+
const unwrapRepeatGroup = (group, repeat) => {
|
|
34094
|
+
normalizeRepeatGroupAttributes(group, repeat);
|
|
34095
|
+
normalizeRepeatGroupLabel(group, repeat);
|
|
34096
|
+
group.replaceWith(repeat);
|
|
34097
|
+
};
|
|
34098
|
+
const normalizeRepeatGroups = (body) => {
|
|
34055
34099
|
const repeats = body.querySelectorAll("repeat");
|
|
34056
34100
|
for (const repeat of repeats) {
|
|
34057
34101
|
const parent = repeat.parentElement;
|
|
@@ -34066,11 +34110,8 @@ const normalizeRepeatGroups = (xformDocument, body) => {
|
|
|
34066
34110
|
group = parent;
|
|
34067
34111
|
}
|
|
34068
34112
|
}
|
|
34069
|
-
if (group
|
|
34070
|
-
group
|
|
34071
|
-
group.setAttribute("ref", repeatNodeset);
|
|
34072
|
-
repeat.before(group);
|
|
34073
|
-
group.append(repeat);
|
|
34113
|
+
if (group != null) {
|
|
34114
|
+
unwrapRepeatGroup(group, repeat);
|
|
34074
34115
|
}
|
|
34075
34116
|
}
|
|
34076
34117
|
};
|
|
@@ -34088,7 +34129,7 @@ const parseNormalizedXForm = (sourceXML, options) => {
|
|
|
34088
34129
|
normalizedXML = sourceXML;
|
|
34089
34130
|
} else {
|
|
34090
34131
|
normalizeBodyRefNodesetAttributes(body);
|
|
34091
|
-
normalizeRepeatGroups(
|
|
34132
|
+
normalizeRepeatGroups(body);
|
|
34092
34133
|
normalizedXML = html.outerHTML;
|
|
34093
34134
|
}
|
|
34094
34135
|
return {
|
|
@@ -34220,6 +34261,70 @@ class DependencyContext {
|
|
|
34220
34261
|
}
|
|
34221
34262
|
}
|
|
34222
34263
|
|
|
34264
|
+
const XML_XPATH_WHITESPACE_SUBPATTERN = "[\\x20\\x09\\x0D\\x0A]";
|
|
34265
|
+
const XML_XPATH_WHITESPACE_PATTERN = new RegExp(XML_XPATH_WHITESPACE_SUBPATTERN, "g");
|
|
34266
|
+
const XML_XPATH_LEADING_TRAILING_WHITESPACE_PATTERN = new RegExp(
|
|
34267
|
+
`^${XML_XPATH_WHITESPACE_SUBPATTERN}+|${XML_XPATH_WHITESPACE_SUBPATTERN}+$`,
|
|
34268
|
+
"g"
|
|
34269
|
+
);
|
|
34270
|
+
const XPATH_REPEATING_WHITESPACE_PATTERN = new RegExp(
|
|
34271
|
+
`${XML_XPATH_WHITESPACE_SUBPATTERN}{2,}`,
|
|
34272
|
+
"g"
|
|
34273
|
+
);
|
|
34274
|
+
const trimXMLXPathWhitespace = (value) => value.replaceAll(XML_XPATH_LEADING_TRAILING_WHITESPACE_PATTERN, "");
|
|
34275
|
+
const normalizeXMLXPathWhitespace = (value) => trimXMLXPathWhitespace(value).replaceAll(XPATH_REPEATING_WHITESPACE_PATTERN, " ");
|
|
34276
|
+
const xmlXPathWhitespaceSeparatedList = (value, options) => {
|
|
34277
|
+
if (options?.ignoreEmpty && value === "") {
|
|
34278
|
+
return [];
|
|
34279
|
+
}
|
|
34280
|
+
return normalizeXMLXPathWhitespace(value).split(XML_XPATH_WHITESPACE_PATTERN);
|
|
34281
|
+
};
|
|
34282
|
+
|
|
34283
|
+
class TokenListParser {
|
|
34284
|
+
constructor(canonicalTokens, options) {
|
|
34285
|
+
this.canonicalTokens = canonicalTokens;
|
|
34286
|
+
this.aliases = new Map(
|
|
34287
|
+
(options?.aliases ?? []).map(({ fromAlias, toCanonical }) => {
|
|
34288
|
+
return [fromAlias, toCanonical];
|
|
34289
|
+
})
|
|
34290
|
+
);
|
|
34291
|
+
}
|
|
34292
|
+
aliases;
|
|
34293
|
+
parseFrom(element, attributeName) {
|
|
34294
|
+
const serialized = element.getAttribute(attributeName) ?? "";
|
|
34295
|
+
const specified = xmlXPathWhitespaceSeparatedList(serialized, {
|
|
34296
|
+
ignoreEmpty: true
|
|
34297
|
+
});
|
|
34298
|
+
const { aliases } = this;
|
|
34299
|
+
const resolved = specified.flatMap((token) => {
|
|
34300
|
+
const alias = aliases.get(token);
|
|
34301
|
+
if (alias == null) {
|
|
34302
|
+
return token;
|
|
34303
|
+
}
|
|
34304
|
+
return [alias, token];
|
|
34305
|
+
});
|
|
34306
|
+
const tokens = new Set(resolved);
|
|
34307
|
+
return new Proxy(
|
|
34308
|
+
{
|
|
34309
|
+
[Symbol.iterator]() {
|
|
34310
|
+
return resolved.values();
|
|
34311
|
+
}
|
|
34312
|
+
},
|
|
34313
|
+
{
|
|
34314
|
+
get(target, property, receiver) {
|
|
34315
|
+
if (typeof property === "symbol") {
|
|
34316
|
+
return Reflect.get(target, property, receiver);
|
|
34317
|
+
}
|
|
34318
|
+
return tokens.has(property);
|
|
34319
|
+
},
|
|
34320
|
+
set() {
|
|
34321
|
+
return false;
|
|
34322
|
+
}
|
|
34323
|
+
}
|
|
34324
|
+
);
|
|
34325
|
+
}
|
|
34326
|
+
}
|
|
34327
|
+
|
|
34223
34328
|
class BodyElementDefinition extends DependencyContext {
|
|
34224
34329
|
constructor(form, parent, element) {
|
|
34225
34330
|
super();
|
|
@@ -34244,17 +34349,7 @@ class BodyElementDefinition extends DependencyContext {
|
|
|
34244
34349
|
}
|
|
34245
34350
|
}
|
|
34246
34351
|
|
|
34247
|
-
|
|
34248
|
-
static isCompatible() {
|
|
34249
|
-
return true;
|
|
34250
|
-
}
|
|
34251
|
-
category = "UNSUPPORTED";
|
|
34252
|
-
type = "UNSUPPORTED";
|
|
34253
|
-
reference = null;
|
|
34254
|
-
constructor(form, parent, element) {
|
|
34255
|
-
super(form, parent, element);
|
|
34256
|
-
}
|
|
34257
|
-
}
|
|
34352
|
+
const structureElementAppearanceParser = new TokenListParser(["field-list", "table-list"]);
|
|
34258
34353
|
|
|
34259
34354
|
const SUPPORTS_SCOPE_CHILD_SELECTOR = (() => {
|
|
34260
34355
|
const parent = document.createElement("parent");
|
|
@@ -34316,7 +34411,10 @@ const hintLookup = new ScopedElementLookup(":scope > hint", "hint");
|
|
|
34316
34411
|
const itemLookup = new ScopedElementLookup(":scope > item", "item");
|
|
34317
34412
|
const itemsetLookup = new ScopedElementLookup(":scope > itemset[nodeset]", "itemset[nodeset]");
|
|
34318
34413
|
const labelLookup = new ScopedElementLookup(":scope > label", "label");
|
|
34319
|
-
const
|
|
34414
|
+
const repeatGroupLabelLookup = new ScopedElementLookup(
|
|
34415
|
+
':scope > label[form-definition-source="repeat-group"]',
|
|
34416
|
+
'label[form-definition-source="repeat-group"]'
|
|
34417
|
+
);
|
|
34320
34418
|
const valueLookup = new ScopedElementLookup(":scope > value", "value");
|
|
34321
34419
|
const getHintElement = (parent) => {
|
|
34322
34420
|
return hintLookup.getElement(parent);
|
|
@@ -34330,8 +34428,8 @@ const getItemsetElement = (parent) => {
|
|
|
34330
34428
|
const getLabelElement = (parent) => {
|
|
34331
34429
|
return labelLookup.getElement(parent);
|
|
34332
34430
|
};
|
|
34333
|
-
const
|
|
34334
|
-
return
|
|
34431
|
+
const getRepeatGroupLabelElement = (parent) => {
|
|
34432
|
+
return repeatGroupLabelLookup.getElement(parent);
|
|
34335
34433
|
};
|
|
34336
34434
|
const getValueElement = (parent) => {
|
|
34337
34435
|
return valueLookup.getElement(parent);
|
|
@@ -34639,17 +34737,6 @@ class TextElementDefinition extends BodyElementDefinition {
|
|
|
34639
34737
|
}
|
|
34640
34738
|
}
|
|
34641
34739
|
|
|
34642
|
-
class HintDefinition extends TextElementDefinition {
|
|
34643
|
-
static forElement(form, definition) {
|
|
34644
|
-
const hintElement = getHintElement(definition.element);
|
|
34645
|
-
if (hintElement == null) {
|
|
34646
|
-
return null;
|
|
34647
|
-
}
|
|
34648
|
-
return new this(form, definition, hintElement);
|
|
34649
|
-
}
|
|
34650
|
-
type = "hint";
|
|
34651
|
-
}
|
|
34652
|
-
|
|
34653
34740
|
class LabelDefinition extends TextElementDefinition {
|
|
34654
34741
|
static staticDefinition(form, definition) {
|
|
34655
34742
|
const labelElement = getLabelElement(definition.element);
|
|
@@ -34661,6 +34748,13 @@ class LabelDefinition extends TextElementDefinition {
|
|
|
34661
34748
|
static forControl(form, control) {
|
|
34662
34749
|
return this.staticDefinition(form, control);
|
|
34663
34750
|
}
|
|
34751
|
+
static forRepeatGroup(form, repeat) {
|
|
34752
|
+
const repeatGroupLabel = getRepeatGroupLabelElement(repeat.element);
|
|
34753
|
+
if (repeatGroupLabel == null) {
|
|
34754
|
+
return null;
|
|
34755
|
+
}
|
|
34756
|
+
return new this(form, repeat, repeatGroupLabel);
|
|
34757
|
+
}
|
|
34664
34758
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
34665
34759
|
static forGroup(form, group) {
|
|
34666
34760
|
return this.staticDefinition(form, group);
|
|
@@ -34678,6 +34772,68 @@ class LabelDefinition extends TextElementDefinition {
|
|
|
34678
34772
|
type = "label";
|
|
34679
34773
|
}
|
|
34680
34774
|
|
|
34775
|
+
class RepeatElementDefinition extends BodyElementDefinition {
|
|
34776
|
+
static isCompatible(localName) {
|
|
34777
|
+
return localName === "repeat";
|
|
34778
|
+
}
|
|
34779
|
+
category = "structure";
|
|
34780
|
+
type = "repeat";
|
|
34781
|
+
reference;
|
|
34782
|
+
appearances;
|
|
34783
|
+
label;
|
|
34784
|
+
// TODO: this will fall into the growing category of non-`BindExpression`
|
|
34785
|
+
// cases which have roughly the same design story.
|
|
34786
|
+
countExpression;
|
|
34787
|
+
isFixedCount;
|
|
34788
|
+
children;
|
|
34789
|
+
constructor(form, parent, element) {
|
|
34790
|
+
super(form, parent, element);
|
|
34791
|
+
this.label = LabelDefinition.forRepeatGroup(form, this);
|
|
34792
|
+
const reference = element.getAttribute("nodeset");
|
|
34793
|
+
if (reference == null) {
|
|
34794
|
+
throw new Error("Invalid repeat: missing `nodeset` reference");
|
|
34795
|
+
}
|
|
34796
|
+
this.reference = reference;
|
|
34797
|
+
this.appearances = structureElementAppearanceParser.parseFrom(element, "appearance");
|
|
34798
|
+
this.countExpression = element.getAttributeNS(JAVAROSA_NAMESPACE_URI$1, "count");
|
|
34799
|
+
const childElements = Array.from(element.children).filter((childElement) => {
|
|
34800
|
+
const { localName } = childElement;
|
|
34801
|
+
return localName !== "label" && localName !== "group-label";
|
|
34802
|
+
});
|
|
34803
|
+
const children = BodyDefinition.getChildElementDefinitions(form, this, element, childElements);
|
|
34804
|
+
this.children = children;
|
|
34805
|
+
const noAddRemove = element.getAttributeNS(JAVAROSA_NAMESPACE_URI$1, "noAddRemove")?.trim().replaceAll(/\s+/g, "") ?? "false()";
|
|
34806
|
+
this.isFixedCount = noAddRemove === "true()";
|
|
34807
|
+
}
|
|
34808
|
+
toJSON() {
|
|
34809
|
+
const { form, parent, ...rest } = this;
|
|
34810
|
+
return rest;
|
|
34811
|
+
}
|
|
34812
|
+
}
|
|
34813
|
+
|
|
34814
|
+
class UnsupportedBodyElementDefinition extends BodyElementDefinition {
|
|
34815
|
+
static isCompatible() {
|
|
34816
|
+
return true;
|
|
34817
|
+
}
|
|
34818
|
+
category = "UNSUPPORTED";
|
|
34819
|
+
type = "UNSUPPORTED";
|
|
34820
|
+
reference = null;
|
|
34821
|
+
constructor(form, parent, element) {
|
|
34822
|
+
super(form, parent, element);
|
|
34823
|
+
}
|
|
34824
|
+
}
|
|
34825
|
+
|
|
34826
|
+
class HintDefinition extends TextElementDefinition {
|
|
34827
|
+
static forElement(form, definition) {
|
|
34828
|
+
const hintElement = getHintElement(definition.element);
|
|
34829
|
+
if (hintElement == null) {
|
|
34830
|
+
return null;
|
|
34831
|
+
}
|
|
34832
|
+
return new this(form, definition, hintElement);
|
|
34833
|
+
}
|
|
34834
|
+
type = "hint";
|
|
34835
|
+
}
|
|
34836
|
+
|
|
34681
34837
|
class ControlDefinition extends BodyElementDefinition {
|
|
34682
34838
|
category = "control";
|
|
34683
34839
|
reference;
|
|
@@ -34695,13 +34851,84 @@ class ControlDefinition extends BodyElementDefinition {
|
|
|
34695
34851
|
}
|
|
34696
34852
|
}
|
|
34697
34853
|
|
|
34854
|
+
const inputAppearanceParser = new TokenListParser([
|
|
34855
|
+
"multiline",
|
|
34856
|
+
"numbers",
|
|
34857
|
+
"url",
|
|
34858
|
+
"thousand-sep",
|
|
34859
|
+
// date (TODO: data types)
|
|
34860
|
+
"no-calendar",
|
|
34861
|
+
"month-year",
|
|
34862
|
+
"year",
|
|
34863
|
+
// date > calendars
|
|
34864
|
+
"ethiopian",
|
|
34865
|
+
"coptic",
|
|
34866
|
+
"islamic",
|
|
34867
|
+
"bikram-sambat",
|
|
34868
|
+
"myanmar",
|
|
34869
|
+
"persian",
|
|
34870
|
+
// geo (TODO: data types)
|
|
34871
|
+
"placement-map",
|
|
34872
|
+
"maps",
|
|
34873
|
+
// image/media (TODO: move to eventual `<upload>`?)
|
|
34874
|
+
"hidden-answer",
|
|
34875
|
+
"annotate",
|
|
34876
|
+
"draw",
|
|
34877
|
+
"signature",
|
|
34878
|
+
"new-front",
|
|
34879
|
+
"new",
|
|
34880
|
+
"front",
|
|
34881
|
+
// *?
|
|
34882
|
+
"printer",
|
|
34883
|
+
// Note: actual usage uses `printer:...` (like `ex:...`).
|
|
34884
|
+
"masked"
|
|
34885
|
+
]);
|
|
34886
|
+
|
|
34698
34887
|
class InputDefinition extends ControlDefinition {
|
|
34699
34888
|
static isCompatible(localName) {
|
|
34700
34889
|
return localName === "input";
|
|
34701
34890
|
}
|
|
34702
34891
|
type = "input";
|
|
34892
|
+
appearances;
|
|
34893
|
+
constructor(form, parent, element) {
|
|
34894
|
+
super(form, parent, element);
|
|
34895
|
+
this.appearances = inputAppearanceParser.parseFrom(element, "appearance");
|
|
34896
|
+
}
|
|
34703
34897
|
}
|
|
34704
34898
|
|
|
34899
|
+
const selectAppearanceParser = new TokenListParser(
|
|
34900
|
+
[
|
|
34901
|
+
// From XLSForm Docs:
|
|
34902
|
+
"compact",
|
|
34903
|
+
"horizontal",
|
|
34904
|
+
"horizontal-compact",
|
|
34905
|
+
"label",
|
|
34906
|
+
"list-nolabel",
|
|
34907
|
+
"minimal",
|
|
34908
|
+
// From Collect `Appearances.kt`:
|
|
34909
|
+
"columns",
|
|
34910
|
+
"columns-1",
|
|
34911
|
+
"columns-2",
|
|
34912
|
+
"columns-3",
|
|
34913
|
+
"columns-4",
|
|
34914
|
+
"columns-5",
|
|
34915
|
+
// Note: Collect supports arbitrary columns-n. Technically we do too (we parse
|
|
34916
|
+
// out any appearance, not just those we know about). But we'll only include
|
|
34917
|
+
// types/defaults up to 5.
|
|
34918
|
+
"columns-pack",
|
|
34919
|
+
"autocomplete",
|
|
34920
|
+
// TODO: these are `<select1>` only
|
|
34921
|
+
"likert",
|
|
34922
|
+
"quick",
|
|
34923
|
+
"quickcompact",
|
|
34924
|
+
"map"
|
|
34925
|
+
// "quick map"
|
|
34926
|
+
],
|
|
34927
|
+
{
|
|
34928
|
+
aliases: [{ fromAlias: "search", toCanonical: "autocomplete" }]
|
|
34929
|
+
}
|
|
34930
|
+
);
|
|
34931
|
+
|
|
34705
34932
|
class ItemDefinition extends BodyElementDefinition {
|
|
34706
34933
|
constructor(form, parent, element) {
|
|
34707
34934
|
const valueElement = getValueElement(element);
|
|
@@ -34755,7 +34982,11 @@ class ItemsetDefinition extends BodyElementDefinition {
|
|
|
34755
34982
|
}
|
|
34756
34983
|
}
|
|
34757
34984
|
|
|
34758
|
-
const selectLocalNames = /* @__PURE__ */ new Set([
|
|
34985
|
+
const selectLocalNames = /* @__PURE__ */ new Set([
|
|
34986
|
+
/* 'rank', */
|
|
34987
|
+
"select",
|
|
34988
|
+
"select1"
|
|
34989
|
+
]);
|
|
34759
34990
|
const isSelectElement = (element, localName = element.localName) => {
|
|
34760
34991
|
return selectLocalNames.has(localName);
|
|
34761
34992
|
};
|
|
@@ -34768,6 +34999,7 @@ class SelectDefinition extends ControlDefinition {
|
|
|
34768
34999
|
}
|
|
34769
35000
|
type;
|
|
34770
35001
|
element;
|
|
35002
|
+
appearances;
|
|
34771
35003
|
itemset;
|
|
34772
35004
|
items;
|
|
34773
35005
|
constructor(form, parent, element) {
|
|
@@ -34775,8 +35007,9 @@ class SelectDefinition extends ControlDefinition {
|
|
|
34775
35007
|
throw new Error(`Invalid select element: <${element.nodeName}>`);
|
|
34776
35008
|
}
|
|
34777
35009
|
super(form, parent, element);
|
|
34778
|
-
this.element = element;
|
|
34779
35010
|
this.type = element.localName;
|
|
35011
|
+
this.element = element;
|
|
35012
|
+
this.appearances = selectAppearanceParser.parseFrom(element, "appearance");
|
|
34780
35013
|
const itemsetElement = getItemsetElement(element);
|
|
34781
35014
|
const itemElements = getItemElements(element);
|
|
34782
35015
|
if (itemsetElement == null) {
|
|
@@ -34809,22 +35042,16 @@ class UpsertableMap extends Map {
|
|
|
34809
35042
|
}
|
|
34810
35043
|
|
|
34811
35044
|
class BaseGroupDefinition extends BodyElementDefinition {
|
|
35045
|
+
// TODO: does this really accomplish anything? It seems highly unlikely it
|
|
35046
|
+
// has enough performance benefit to outweigh its memory and lookup costs.
|
|
34812
35047
|
static groupTypes = new UpsertableMap();
|
|
34813
35048
|
static getGroupType(localName, element) {
|
|
34814
35049
|
return this.groupTypes.upsert(element, () => {
|
|
34815
35050
|
if (localName !== "group") {
|
|
34816
35051
|
return null;
|
|
34817
35052
|
}
|
|
34818
|
-
|
|
34819
|
-
|
|
34820
|
-
const repeat = getRepeatElement(element);
|
|
34821
|
-
if (repeat == null) {
|
|
34822
|
-
return "logical-group";
|
|
34823
|
-
}
|
|
34824
|
-
if (repeat.getAttribute("nodeset") === ref) {
|
|
34825
|
-
return "repeat-group";
|
|
34826
|
-
}
|
|
34827
|
-
throw new Error("Unexpected <repeat> child of unrelated <group>");
|
|
35053
|
+
if (element.hasAttribute("ref")) {
|
|
35054
|
+
return "logical-group";
|
|
34828
35055
|
}
|
|
34829
35056
|
const label = getLabelElement(element);
|
|
34830
35057
|
if (label == null) {
|
|
@@ -34836,18 +35063,20 @@ class BaseGroupDefinition extends BodyElementDefinition {
|
|
|
34836
35063
|
category = "structure";
|
|
34837
35064
|
children;
|
|
34838
35065
|
reference;
|
|
35066
|
+
appearances;
|
|
34839
35067
|
label;
|
|
34840
35068
|
constructor(form, parent, element, children) {
|
|
34841
35069
|
super(form, parent, element);
|
|
34842
35070
|
this.children = children ?? this.getChildren(element);
|
|
34843
35071
|
this.reference = element.getAttribute("ref");
|
|
35072
|
+
this.appearances = structureElementAppearanceParser.parseFrom(element, "appearance");
|
|
34844
35073
|
this.label = LabelDefinition.forGroup(form, this);
|
|
34845
35074
|
}
|
|
34846
35075
|
getChildren(element) {
|
|
34847
35076
|
const { form } = this;
|
|
34848
35077
|
const children = Array.from(element.children).filter((child) => {
|
|
34849
35078
|
const childName = child.localName;
|
|
34850
|
-
return childName !== "label"
|
|
35079
|
+
return childName !== "label";
|
|
34851
35080
|
});
|
|
34852
35081
|
return BodyDefinition.getChildElementDefinitions(form, this, element, children);
|
|
34853
35082
|
}
|
|
@@ -34876,54 +35105,6 @@ class PresentationGroupDefinition extends BaseGroupDefinition {
|
|
|
34876
35105
|
}
|
|
34877
35106
|
}
|
|
34878
35107
|
|
|
34879
|
-
class RepeatDefinition extends BodyElementDefinition {
|
|
34880
|
-
constructor(form, groupDefinition, element) {
|
|
34881
|
-
super(form, groupDefinition, element);
|
|
34882
|
-
this.groupDefinition = groupDefinition;
|
|
34883
|
-
const reference = element.getAttribute("nodeset");
|
|
34884
|
-
if (reference == null) {
|
|
34885
|
-
throw new Error("Invalid repeat: missing `nodeset` reference");
|
|
34886
|
-
}
|
|
34887
|
-
this.reference = reference;
|
|
34888
|
-
this.countExpression = element.getAttributeNS(JAVAROSA_NAMESPACE_URI$1, "count");
|
|
34889
|
-
this.children = groupDefinition.getChildren(element);
|
|
34890
|
-
const noAddRemove = element.getAttributeNS(JAVAROSA_NAMESPACE_URI$1, "noAddRemove")?.trim().replaceAll(/\s+/g, "") ?? "false()";
|
|
34891
|
-
this.isFixedCount = noAddRemove === "true()";
|
|
34892
|
-
}
|
|
34893
|
-
category = "structure";
|
|
34894
|
-
type = "repeat";
|
|
34895
|
-
reference;
|
|
34896
|
-
// TODO: this will fall into the growing category of non-`BindExpression`
|
|
34897
|
-
// cases which have roughly the same design story.
|
|
34898
|
-
countExpression;
|
|
34899
|
-
isFixedCount;
|
|
34900
|
-
children;
|
|
34901
|
-
toJSON() {
|
|
34902
|
-
const { form, groupDefinition, parent, ...rest } = this;
|
|
34903
|
-
return rest;
|
|
34904
|
-
}
|
|
34905
|
-
}
|
|
34906
|
-
|
|
34907
|
-
class RepeatGroupDefinition extends BaseGroupDefinition {
|
|
34908
|
-
static isCompatible(localName, element) {
|
|
34909
|
-
return this.getGroupType(localName, element) === "repeat-group";
|
|
34910
|
-
}
|
|
34911
|
-
type = "repeat-group";
|
|
34912
|
-
repeat;
|
|
34913
|
-
get repeatChildren() {
|
|
34914
|
-
return this.repeat.children;
|
|
34915
|
-
}
|
|
34916
|
-
constructor(form, parent, element) {
|
|
34917
|
-
const repeat = getRepeatElement(element);
|
|
34918
|
-
if (repeat == null) {
|
|
34919
|
-
throw new Error("Invalid repeat-group");
|
|
34920
|
-
}
|
|
34921
|
-
super(form, parent, element);
|
|
34922
|
-
const repeatDefinition = new RepeatDefinition(form, this, repeat);
|
|
34923
|
-
this.repeat = repeatDefinition;
|
|
34924
|
-
}
|
|
34925
|
-
}
|
|
34926
|
-
|
|
34927
35108
|
class StructuralGroupDefinition extends BaseGroupDefinition {
|
|
34928
35109
|
static isCompatible(localName, element) {
|
|
34929
35110
|
return this.getGroupType(localName, element) === "structural-group";
|
|
@@ -34932,7 +35113,7 @@ class StructuralGroupDefinition extends BaseGroupDefinition {
|
|
|
34932
35113
|
}
|
|
34933
35114
|
|
|
34934
35115
|
const BodyElementDefinitionConstructors = [
|
|
34935
|
-
|
|
35116
|
+
RepeatElementDefinition,
|
|
34936
35117
|
LogicalGroupDefinition,
|
|
34937
35118
|
PresentationGroupDefinition,
|
|
34938
35119
|
StructuralGroupDefinition,
|
|
@@ -34947,12 +35128,12 @@ class BodyElementMap extends Map {
|
|
|
34947
35128
|
mapElementsByReference(elements) {
|
|
34948
35129
|
for (const element of elements) {
|
|
34949
35130
|
const { reference } = element;
|
|
34950
|
-
if (element instanceof
|
|
35131
|
+
if (element instanceof RepeatElementDefinition) {
|
|
34951
35132
|
if (reference == null) {
|
|
34952
|
-
throw new Error("Missing reference for repeat
|
|
35133
|
+
throw new Error("Missing reference for repeat");
|
|
34953
35134
|
}
|
|
34954
35135
|
this.set(reference, element);
|
|
34955
|
-
this.mapElementsByReference(element.
|
|
35136
|
+
this.mapElementsByReference(element.children);
|
|
34956
35137
|
}
|
|
34957
35138
|
if (element instanceof LogicalGroupDefinition || element instanceof PresentationGroupDefinition || element instanceof StructuralGroupDefinition) {
|
|
34958
35139
|
if (reference != null) {
|
|
@@ -34978,6 +35159,10 @@ class BodyElementMap extends Map {
|
|
|
34978
35159
|
return Object.fromEntries(this.entries());
|
|
34979
35160
|
}
|
|
34980
35161
|
}
|
|
35162
|
+
const bodyClassParser = new TokenListParser([
|
|
35163
|
+
"pages"
|
|
35164
|
+
/*, 'theme-grid' */
|
|
35165
|
+
]);
|
|
34981
35166
|
class BodyDefinition extends DependencyContext {
|
|
34982
35167
|
constructor(form) {
|
|
34983
35168
|
super();
|
|
@@ -34985,6 +35170,7 @@ class BodyDefinition extends DependencyContext {
|
|
|
34985
35170
|
const { body: element } = form.xformDOM;
|
|
34986
35171
|
this.reference = form.rootReference;
|
|
34987
35172
|
this.element = element;
|
|
35173
|
+
this.classes = bodyClassParser.parseFrom(element, "class");
|
|
34988
35174
|
this.elements = BodyDefinition.getChildElementDefinitions(form, this, element);
|
|
34989
35175
|
this.elementsByReference = new BodyElementMap(this.elements);
|
|
34990
35176
|
}
|
|
@@ -35000,6 +35186,23 @@ class BodyDefinition extends DependencyContext {
|
|
|
35000
35186
|
});
|
|
35001
35187
|
}
|
|
35002
35188
|
element;
|
|
35189
|
+
/**
|
|
35190
|
+
* @todo this class is already an oddity in that it's **like** an element
|
|
35191
|
+
* definition, but it isn't one itself. Adding this property here emphasizes
|
|
35192
|
+
* that awkwardness. It also extends the applicable scope where instances of
|
|
35193
|
+
* this class are accessed. While it's still ephemeral, it's anticipated that
|
|
35194
|
+
* this extension might cause some disomfort. If so, the most plausible
|
|
35195
|
+
* alternative is an additional refactor to:
|
|
35196
|
+
*
|
|
35197
|
+
* 1. Introduce a `BodyElementDefinition` sublass for `<h:body>`.
|
|
35198
|
+
* 2. Disambiguate the respective names of those, in some reasonable way.
|
|
35199
|
+
* 3. Add a layer of indirection between this class and that new body element
|
|
35200
|
+
* definition's class.
|
|
35201
|
+
* 4. At that point, we may as well prioritize the little bit of grunt work to
|
|
35202
|
+
* pass the `BodyDefinition` instance by reference rather than assigning it
|
|
35203
|
+
* to anything.
|
|
35204
|
+
*/
|
|
35205
|
+
classes;
|
|
35003
35206
|
elements;
|
|
35004
35207
|
elementsByReference;
|
|
35005
35208
|
// DependencyContext
|
|
@@ -35008,13 +35211,6 @@ class BodyDefinition extends DependencyContext {
|
|
|
35008
35211
|
getBodyElement(reference) {
|
|
35009
35212
|
return this.elementsByReference.get(reference) ?? null;
|
|
35010
35213
|
}
|
|
35011
|
-
getRepeatGroup(reference) {
|
|
35012
|
-
const element = this.getBodyElement(reference);
|
|
35013
|
-
if (element?.type === "repeat-group") {
|
|
35014
|
-
return element;
|
|
35015
|
-
}
|
|
35016
|
-
return null;
|
|
35017
|
-
}
|
|
35018
35214
|
toJSON() {
|
|
35019
35215
|
const { form, ...rest } = this;
|
|
35020
35216
|
return rest;
|
|
@@ -35247,17 +35443,11 @@ class DescendentNodeDefinition {
|
|
|
35247
35443
|
}
|
|
35248
35444
|
|
|
35249
35445
|
class RepeatInstanceDefinition extends DescendentNodeDefinition {
|
|
35250
|
-
constructor(
|
|
35251
|
-
const {
|
|
35252
|
-
|
|
35253
|
-
bodyElement: repeatGroupBodyElement,
|
|
35254
|
-
parent: repeatSequenceParent,
|
|
35255
|
-
root
|
|
35256
|
-
} = sequence;
|
|
35257
|
-
super(repeatSequenceParent, bind, repeatGroupBodyElement.repeat);
|
|
35258
|
-
this.sequence = sequence;
|
|
35446
|
+
constructor(range, node) {
|
|
35447
|
+
const { bind, bodyElement, parent, root } = range;
|
|
35448
|
+
super(parent, bind, bodyElement);
|
|
35259
35449
|
this.node = node;
|
|
35260
|
-
this.nodeName =
|
|
35450
|
+
this.nodeName = range.nodeName;
|
|
35261
35451
|
this.children = root.buildSubtree(this);
|
|
35262
35452
|
}
|
|
35263
35453
|
type = "repeat-instance";
|
|
@@ -35266,7 +35456,7 @@ class RepeatInstanceDefinition extends DescendentNodeDefinition {
|
|
|
35266
35456
|
instances = null;
|
|
35267
35457
|
defaultValue = null;
|
|
35268
35458
|
toJSON() {
|
|
35269
|
-
const { bind, bodyElement, parent, root,
|
|
35459
|
+
const { bind, bodyElement, parent, root, ...rest } = this;
|
|
35270
35460
|
return rest;
|
|
35271
35461
|
}
|
|
35272
35462
|
}
|
|
@@ -35305,15 +35495,9 @@ const splitInstanceNodes = (modelNodes) => {
|
|
|
35305
35495
|
return [template, ...modelNodes];
|
|
35306
35496
|
};
|
|
35307
35497
|
class RepeatTemplateDefinition extends DescendentNodeDefinition {
|
|
35308
|
-
constructor(
|
|
35309
|
-
const {
|
|
35310
|
-
|
|
35311
|
-
bodyElement: repeatGroupBodyElement,
|
|
35312
|
-
parent: repeatSequenceParent,
|
|
35313
|
-
root
|
|
35314
|
-
} = sequence;
|
|
35315
|
-
super(repeatSequenceParent, bind, repeatGroupBodyElement.repeat);
|
|
35316
|
-
this.sequence = sequence;
|
|
35498
|
+
constructor(range, templateNode) {
|
|
35499
|
+
const { bind, bodyElement, parent, root } = range;
|
|
35500
|
+
super(parent, bind, bodyElement);
|
|
35317
35501
|
this.templateNode = templateNode;
|
|
35318
35502
|
const node = templateNode.cloneNode(true);
|
|
35319
35503
|
node.removeAttributeNS(JAVAROSA_NAMESPACE_URI$1, "template");
|
|
@@ -35321,14 +35505,14 @@ class RepeatTemplateDefinition extends DescendentNodeDefinition {
|
|
|
35321
35505
|
this.nodeName = node.localName;
|
|
35322
35506
|
this.children = root.buildSubtree(this);
|
|
35323
35507
|
}
|
|
35324
|
-
static parseModelNodes(
|
|
35325
|
-
const { bind } =
|
|
35508
|
+
static parseModelNodes(range, modelNodes) {
|
|
35509
|
+
const { bind } = range;
|
|
35326
35510
|
let template = repeatTemplates.get(bind);
|
|
35327
35511
|
let instanceNodes;
|
|
35328
35512
|
if (template == null) {
|
|
35329
35513
|
const [templateNode, ...rest] = splitInstanceNodes(modelNodes);
|
|
35330
35514
|
instanceNodes = rest;
|
|
35331
|
-
template = new this(
|
|
35515
|
+
template = new this(range, templateNode);
|
|
35332
35516
|
} else {
|
|
35333
35517
|
const duplicateTemplate = modelNodes.find(
|
|
35334
35518
|
(node) => node.hasAttributeNS(JAVAROSA_NAMESPACE_URI$1, "template")
|
|
@@ -35350,12 +35534,12 @@ class RepeatTemplateDefinition extends DescendentNodeDefinition {
|
|
|
35350
35534
|
instances = null;
|
|
35351
35535
|
defaultValue = null;
|
|
35352
35536
|
toJSON() {
|
|
35353
|
-
const { bind, bodyElement, parent, root,
|
|
35537
|
+
const { bind, bodyElement, parent, root, ...rest } = this;
|
|
35354
35538
|
return rest;
|
|
35355
35539
|
}
|
|
35356
35540
|
}
|
|
35357
35541
|
|
|
35358
|
-
class
|
|
35542
|
+
class RepeatRangeDefinition extends DescendentNodeDefinition {
|
|
35359
35543
|
// TODO: if an implicit template is derived from an instance in a form
|
|
35360
35544
|
// definition, should its default values (if any) be cleared? Probably!
|
|
35361
35545
|
static createTemplateElement(instanceElement) {
|
|
@@ -35364,7 +35548,7 @@ class RepeatSequenceDefinition extends DescendentNodeDefinition {
|
|
|
35364
35548
|
static createInstanceElement(templateElement) {
|
|
35365
35549
|
return templateElement.cloneNode(true);
|
|
35366
35550
|
}
|
|
35367
|
-
type = "repeat-
|
|
35551
|
+
type = "repeat-range";
|
|
35368
35552
|
template;
|
|
35369
35553
|
children = null;
|
|
35370
35554
|
instances;
|
|
@@ -35388,7 +35572,7 @@ class RepeatSequenceDefinition extends DescendentNodeDefinition {
|
|
|
35388
35572
|
|
|
35389
35573
|
class SubtreeDefinition extends DescendentNodeDefinition {
|
|
35390
35574
|
constructor(parent, bind, bodyElement, node) {
|
|
35391
|
-
if (bodyElement != null && (bodyElement.category !== "structure" || bodyElement.type === "repeat
|
|
35575
|
+
if (bodyElement != null && (bodyElement.category !== "structure" || bodyElement.type === "repeat")) {
|
|
35392
35576
|
throw new Error(`Unexpected body element for nodeset ${bind.nodeset}`);
|
|
35393
35577
|
}
|
|
35394
35578
|
super(parent, bind, bodyElement);
|
|
@@ -35430,9 +35614,10 @@ class ValueNodeDefinition extends DescendentNodeDefinition {
|
|
|
35430
35614
|
}
|
|
35431
35615
|
|
|
35432
35616
|
class RootDefinition {
|
|
35433
|
-
constructor(form, model) {
|
|
35617
|
+
constructor(form, model, classes) {
|
|
35434
35618
|
this.form = form;
|
|
35435
35619
|
this.model = model;
|
|
35620
|
+
this.classes = classes;
|
|
35436
35621
|
const { primaryInstanceRoot } = form.xformDOM;
|
|
35437
35622
|
const { localName: rootNodeName } = primaryInstanceRoot;
|
|
35438
35623
|
this.nodeName = rootNodeName;
|
|
@@ -35481,13 +35666,8 @@ class RootDefinition {
|
|
|
35481
35666
|
const bind = binds.getOrCreateBindDefinition(nodeset);
|
|
35482
35667
|
const bodyElement = body.getBodyElement(nodeset);
|
|
35483
35668
|
const [firstChild, ...restChildren] = children;
|
|
35484
|
-
|
|
35485
|
-
|
|
35486
|
-
const repeatDefinition = bodyElement.repeat;
|
|
35487
|
-
if (repeatDefinition == null) {
|
|
35488
|
-
throw 'TODO: this is why I have hesitated to pick an "is repeat" predicate direction';
|
|
35489
|
-
}
|
|
35490
|
-
return new RepeatSequenceDefinition(parent, bind, repeatGroup, children);
|
|
35669
|
+
if (bodyElement?.type === "repeat") {
|
|
35670
|
+
return new RepeatRangeDefinition(parent, bind, bodyElement, children);
|
|
35491
35671
|
}
|
|
35492
35672
|
if (restChildren.length) {
|
|
35493
35673
|
throw new Error(`Unexpected: multiple elements for non-repeat nodeset: ${nodeset}`);
|
|
@@ -35510,7 +35690,7 @@ class ModelDefinition {
|
|
|
35510
35690
|
constructor(form) {
|
|
35511
35691
|
this.form = form;
|
|
35512
35692
|
this.binds = ModelBindMap.fromModel(this);
|
|
35513
|
-
this.root = new RootDefinition(form, this);
|
|
35693
|
+
this.root = new RootDefinition(form, this, form.body.classes);
|
|
35514
35694
|
}
|
|
35515
35695
|
binds;
|
|
35516
35696
|
root;
|
|
@@ -35994,11 +36174,26 @@ const createUniqueId = (() => {
|
|
|
35994
36174
|
|
|
35995
36175
|
const createChildrenState = (parent) => {
|
|
35996
36176
|
return parent.scope.runTask(() => {
|
|
35997
|
-
const
|
|
35998
|
-
const [getChildren,
|
|
35999
|
-
const
|
|
36000
|
-
|
|
36001
|
-
|
|
36177
|
+
const baseState = createSignal([]);
|
|
36178
|
+
const [getChildren, baseSetChildren] = baseState;
|
|
36179
|
+
const ids = createSignal([]);
|
|
36180
|
+
const [childIds, setChildIds] = ids;
|
|
36181
|
+
const setChildren = (valueOrSetterCallback) => {
|
|
36182
|
+
let setterCallback;
|
|
36183
|
+
if (typeof valueOrSetterCallback === "function") {
|
|
36184
|
+
setterCallback = valueOrSetterCallback;
|
|
36185
|
+
} else {
|
|
36186
|
+
setterCallback = (_) => valueOrSetterCallback;
|
|
36187
|
+
}
|
|
36188
|
+
return baseSetChildren((prev) => {
|
|
36189
|
+
const result = setterCallback(prev);
|
|
36190
|
+
setChildIds(() => {
|
|
36191
|
+
return result.map((child) => child.nodeId);
|
|
36192
|
+
});
|
|
36193
|
+
return result;
|
|
36194
|
+
});
|
|
36195
|
+
};
|
|
36196
|
+
const children = [getChildren, setChildren];
|
|
36002
36197
|
return {
|
|
36003
36198
|
children,
|
|
36004
36199
|
getChildren,
|
|
@@ -36008,13 +36203,13 @@ const createChildrenState = (parent) => {
|
|
|
36008
36203
|
});
|
|
36009
36204
|
};
|
|
36010
36205
|
|
|
36011
|
-
const materializeCurrentStateChildren = (currentState, childrenState) => {
|
|
36206
|
+
const materializeCurrentStateChildren = (scope, currentState, childrenState) => {
|
|
36012
36207
|
const baseState = currentState;
|
|
36013
36208
|
const proxyTarget = baseState;
|
|
36014
36209
|
return new Proxy(proxyTarget, {
|
|
36015
36210
|
get(_, key) {
|
|
36016
36211
|
if (key === "children") {
|
|
36017
|
-
currentState.children;
|
|
36212
|
+
scope.runTask(() => currentState.children);
|
|
36018
36213
|
const children = childrenState.getChildren();
|
|
36019
36214
|
return children;
|
|
36020
36215
|
}
|
|
@@ -36217,104 +36412,59 @@ const declareNodeID = (id) => {
|
|
|
36217
36412
|
};
|
|
36218
36413
|
|
|
36219
36414
|
class InstanceNode {
|
|
36220
|
-
constructor(engineConfig, parent, definition) {
|
|
36415
|
+
constructor(engineConfig, parent, definition, options) {
|
|
36221
36416
|
this.engineConfig = engineConfig;
|
|
36222
36417
|
this.parent = parent;
|
|
36223
36418
|
this.definition = definition;
|
|
36419
|
+
this.computeReference = options?.computeReference ?? this.computeChildStepReference;
|
|
36224
36420
|
this.scope = createReactiveScope();
|
|
36225
36421
|
this.engineConfig = engineConfig;
|
|
36226
36422
|
this.nodeId = declareNodeID(engineConfig.createUniqueId());
|
|
36227
36423
|
this.definition = definition;
|
|
36228
|
-
const checkStateInitialized = () => this.engineState != null;
|
|
36229
|
-
const [isStateInitialized, setStateInitialized] = createSignal(checkStateInitialized());
|
|
36230
|
-
this.isStateInitialized = isStateInitialized;
|
|
36231
|
-
queueMicrotask(() => {
|
|
36232
|
-
if (checkStateInitialized()) {
|
|
36233
|
-
setStateInitialized(true);
|
|
36234
|
-
} else {
|
|
36235
|
-
throw new Error("Node state was never initialized");
|
|
36236
|
-
}
|
|
36237
|
-
});
|
|
36238
|
-
}
|
|
36239
|
-
isStateInitialized;
|
|
36240
|
-
/**
|
|
36241
|
-
* Provides a generalized mechanism for accessing a reactive state value
|
|
36242
|
-
* during a node's construction, while {@link engineState} is still being
|
|
36243
|
-
* defined and thus isn't assigned.
|
|
36244
|
-
*
|
|
36245
|
-
* The fallback value specified in {@link options} will be returned on access
|
|
36246
|
-
* until {@link isStateInitialized} returns true. This ensures:
|
|
36247
|
-
*
|
|
36248
|
-
* - a value of the expected type will be available
|
|
36249
|
-
* - any read access will become reactive to the actual state, once it has
|
|
36250
|
-
* been initialized and {@link engineState} is assigned
|
|
36251
|
-
*
|
|
36252
|
-
* @todo This is one among several chicken/egg problems encountered trying to
|
|
36253
|
-
* support state initialization in which some aspects of the state derive from
|
|
36254
|
-
* other aspects of it. It would be nice to dispense with this entirely. But
|
|
36255
|
-
* if it must persist, we should also consider replacing the method with a
|
|
36256
|
-
* direct accessor once state initialization completes, so the initialized
|
|
36257
|
-
* check is only called until it becomes impertinent.
|
|
36258
|
-
*/
|
|
36259
|
-
getInitializedState(key, options) {
|
|
36260
|
-
if (this.isStateInitialized()) {
|
|
36261
|
-
return this.engineState[key];
|
|
36262
|
-
}
|
|
36263
|
-
return options.uninitializedFallback;
|
|
36264
|
-
}
|
|
36265
|
-
/**
|
|
36266
|
-
* @package Exposed on every node type to facilitate inheritance, as well as
|
|
36267
|
-
* conditional behavior for value nodes.
|
|
36268
|
-
*/
|
|
36269
|
-
get isReadonly() {
|
|
36270
|
-
return this.getInitializedState("readonly", {
|
|
36271
|
-
uninitializedFallback: false
|
|
36272
|
-
});
|
|
36273
|
-
}
|
|
36274
|
-
/**
|
|
36275
|
-
* @package Exposed on every node type to facilitate inheritance, as well as
|
|
36276
|
-
* conditional behavior for value nodes.
|
|
36277
|
-
*/
|
|
36278
|
-
get isRelevant() {
|
|
36279
|
-
return this.getInitializedState("relevant", {
|
|
36280
|
-
uninitializedFallback: true
|
|
36281
|
-
});
|
|
36282
36424
|
}
|
|
36283
36425
|
// BaseNode: identity
|
|
36284
36426
|
nodeId;
|
|
36285
36427
|
// EvaluationContext *and* Subscribable: node-specific
|
|
36286
36428
|
scope;
|
|
36429
|
+
computeReference;
|
|
36430
|
+
computeChildStepReference = (parent, definition) => {
|
|
36431
|
+
if (parent == null) {
|
|
36432
|
+
throw new Error(
|
|
36433
|
+
"Cannot compute child step reference of node without parent (was this called from `Root`?)"
|
|
36434
|
+
);
|
|
36435
|
+
}
|
|
36436
|
+
return `${parent.contextReference()}/${definition.nodeName}`;
|
|
36437
|
+
};
|
|
36287
36438
|
// EvaluationContext: node-specific
|
|
36288
|
-
|
|
36439
|
+
contextReference = () => {
|
|
36289
36440
|
return this.computeReference(this.parent, this.definition);
|
|
36290
|
-
}
|
|
36291
|
-
|
|
36441
|
+
};
|
|
36442
|
+
getNodesByReference(visited, dependencyReference) {
|
|
36292
36443
|
if (visited.has(this)) {
|
|
36293
|
-
return
|
|
36444
|
+
return [];
|
|
36294
36445
|
}
|
|
36295
36446
|
visited.add(this);
|
|
36296
36447
|
const { nodeset } = this.definition;
|
|
36297
36448
|
if (dependencyReference === nodeset) {
|
|
36298
|
-
|
|
36449
|
+
if (this.nodeType === "repeat-instance") {
|
|
36450
|
+
return [this.parent];
|
|
36451
|
+
}
|
|
36452
|
+
return [this];
|
|
36299
36453
|
}
|
|
36300
36454
|
if (dependencyReference.startsWith(`${nodeset}/`) || dependencyReference.startsWith(`${nodeset}[`)) {
|
|
36301
|
-
|
|
36302
|
-
|
|
36303
|
-
|
|
36304
|
-
}
|
|
36305
|
-
for (const child of children) {
|
|
36306
|
-
const dependency = child.getNodeByReference(visited, dependencyReference);
|
|
36307
|
-
if (dependency != null) {
|
|
36308
|
-
return dependency;
|
|
36309
|
-
}
|
|
36310
|
-
}
|
|
36455
|
+
return this.getChildren().flatMap((child) => {
|
|
36456
|
+
return child.getNodesByReference(visited, dependencyReference);
|
|
36457
|
+
});
|
|
36311
36458
|
}
|
|
36312
|
-
return this.parent?.
|
|
36459
|
+
return this.parent?.getNodesByReference(visited, dependencyReference) ?? [];
|
|
36313
36460
|
}
|
|
36314
36461
|
// EvaluationContext: node-relative
|
|
36315
|
-
|
|
36316
|
-
|
|
36317
|
-
|
|
36462
|
+
getSubscribableDependenciesByReference(reference) {
|
|
36463
|
+
if (this.nodeType === "root") {
|
|
36464
|
+
const visited = /* @__PURE__ */ new WeakSet();
|
|
36465
|
+
return this.getNodesByReference(visited, reference);
|
|
36466
|
+
}
|
|
36467
|
+
return this.root.getSubscribableDependenciesByReference(reference);
|
|
36318
36468
|
}
|
|
36319
36469
|
// SubscribableDependency
|
|
36320
36470
|
/**
|
|
@@ -36406,7 +36556,7 @@ const createComputedExpression = (context, dependentExpression) => {
|
|
|
36406
36556
|
}
|
|
36407
36557
|
const getReferencedDependencies = createMemo(() => {
|
|
36408
36558
|
return dependencyReferences.flatMap((reference) => {
|
|
36409
|
-
return context.
|
|
36559
|
+
return context.getSubscribableDependenciesByReference(reference) ?? [];
|
|
36410
36560
|
});
|
|
36411
36561
|
});
|
|
36412
36562
|
let getDependencies;
|
|
@@ -36497,42 +36647,45 @@ const createNodeLabel = (context, definition) => {
|
|
|
36497
36647
|
};
|
|
36498
36648
|
|
|
36499
36649
|
class DescendantNode extends InstanceNode {
|
|
36500
|
-
constructor(parent, definition) {
|
|
36501
|
-
super(parent.engineConfig, parent, definition);
|
|
36650
|
+
constructor(parent, definition, options) {
|
|
36651
|
+
super(parent.engineConfig, parent, definition, options);
|
|
36502
36652
|
this.parent = parent;
|
|
36503
36653
|
this.definition = definition;
|
|
36504
36654
|
const { evaluator, root } = parent;
|
|
36505
36655
|
this.root = root;
|
|
36506
36656
|
this.evaluator = evaluator;
|
|
36507
36657
|
this.contextNode = this.initializeContextNode(parent.contextNode, definition.nodeName);
|
|
36508
|
-
|
|
36658
|
+
const { readonly, relevant, required } = definition.bind;
|
|
36659
|
+
this.isSelfReadonly = createComputedExpression(this, readonly);
|
|
36660
|
+
this.isSelfRelevant = createComputedExpression(this, relevant);
|
|
36661
|
+
this.isRequired = createComputedExpression(this, required);
|
|
36662
|
+
}
|
|
36663
|
+
hasReadonlyAncestor = () => {
|
|
36664
|
+
const { parent } = this;
|
|
36665
|
+
return parent.hasReadonlyAncestor() || parent.isReadonly();
|
|
36666
|
+
};
|
|
36667
|
+
isSelfReadonly;
|
|
36668
|
+
isReadonly = () => {
|
|
36669
|
+
if (this.hasReadonlyAncestor()) {
|
|
36670
|
+
return true;
|
|
36671
|
+
}
|
|
36672
|
+
return this.isSelfReadonly();
|
|
36673
|
+
};
|
|
36674
|
+
hasNonRelevantAncestor = () => {
|
|
36675
|
+
const { parent } = this;
|
|
36676
|
+
return parent.hasNonRelevantAncestor() || !parent.isRelevant();
|
|
36677
|
+
};
|
|
36678
|
+
isSelfRelevant;
|
|
36679
|
+
isRelevant = () => {
|
|
36680
|
+
if (this.hasNonRelevantAncestor()) {
|
|
36681
|
+
return false;
|
|
36682
|
+
}
|
|
36683
|
+
return this.isSelfRelevant();
|
|
36684
|
+
};
|
|
36685
|
+
isRequired;
|
|
36509
36686
|
root;
|
|
36510
36687
|
evaluator;
|
|
36511
36688
|
contextNode;
|
|
36512
|
-
computeChildStepReference(parent) {
|
|
36513
|
-
return `${parent.contextReference}/${this.definition.nodeName}`;
|
|
36514
|
-
}
|
|
36515
|
-
buildSharedStateSpec(parent, definition) {
|
|
36516
|
-
return this.scope.runTask(() => {
|
|
36517
|
-
const reference = createMemo(() => this.contextReference);
|
|
36518
|
-
const { bind } = definition;
|
|
36519
|
-
const selfReadonly = createComputedExpression(this, bind.readonly);
|
|
36520
|
-
const readonly = createMemo(() => {
|
|
36521
|
-
return parent.isReadonly || selfReadonly();
|
|
36522
|
-
});
|
|
36523
|
-
const selfRelevant = createComputedExpression(this, bind.relevant);
|
|
36524
|
-
const relevant = createMemo(() => {
|
|
36525
|
-
return parent.isRelevant && selfRelevant();
|
|
36526
|
-
});
|
|
36527
|
-
const required = createComputedExpression(this, bind.required);
|
|
36528
|
-
return {
|
|
36529
|
-
reference,
|
|
36530
|
-
readonly,
|
|
36531
|
-
relevant,
|
|
36532
|
-
required
|
|
36533
|
-
};
|
|
36534
|
-
});
|
|
36535
|
-
}
|
|
36536
36689
|
createContextNode(parentContextNode, nodeName) {
|
|
36537
36690
|
return parentContextNode.ownerDocument.createElement(nodeName);
|
|
36538
36691
|
}
|
|
@@ -36595,16 +36748,21 @@ class Group extends DescendantNode {
|
|
|
36595
36748
|
state;
|
|
36596
36749
|
engineState;
|
|
36597
36750
|
// GroupNode
|
|
36598
|
-
currentState;
|
|
36599
36751
|
nodeType = "group";
|
|
36752
|
+
appearances;
|
|
36753
|
+
currentState;
|
|
36600
36754
|
constructor(parent, definition) {
|
|
36601
36755
|
super(parent, definition);
|
|
36756
|
+
this.appearances = definition.bodyElement.appearances;
|
|
36602
36757
|
const childrenState = createChildrenState(this);
|
|
36603
36758
|
this.childrenState = childrenState;
|
|
36604
36759
|
const state = createSharedNodeState(
|
|
36605
36760
|
this.scope,
|
|
36606
36761
|
{
|
|
36607
|
-
|
|
36762
|
+
reference: this.contextReference,
|
|
36763
|
+
readonly: this.isReadonly,
|
|
36764
|
+
relevant: this.isRelevant,
|
|
36765
|
+
required: this.isRequired,
|
|
36608
36766
|
label: createNodeLabel(this, definition),
|
|
36609
36767
|
hint: null,
|
|
36610
36768
|
children: childrenState.childIds,
|
|
@@ -36617,12 +36775,13 @@ class Group extends DescendantNode {
|
|
|
36617
36775
|
);
|
|
36618
36776
|
this.state = state;
|
|
36619
36777
|
this.engineState = state.engineState;
|
|
36620
|
-
this.currentState = materializeCurrentStateChildren(
|
|
36778
|
+
this.currentState = materializeCurrentStateChildren(
|
|
36779
|
+
this.scope,
|
|
36780
|
+
state.currentState,
|
|
36781
|
+
childrenState
|
|
36782
|
+
);
|
|
36621
36783
|
childrenState.setChildren(buildChildren(this));
|
|
36622
36784
|
}
|
|
36623
|
-
computeReference(parent) {
|
|
36624
|
-
return this.computeChildStepReference(parent);
|
|
36625
|
-
}
|
|
36626
36785
|
getChildren() {
|
|
36627
36786
|
return this.childrenState.getChildren();
|
|
36628
36787
|
}
|
|
@@ -36647,20 +36806,30 @@ const insertAtIndex = (currentValues, insertionIndex, newValue) => {
|
|
|
36647
36806
|
|
|
36648
36807
|
class RepeatInstance extends DescendantNode {
|
|
36649
36808
|
constructor(parent, definition, options) {
|
|
36650
|
-
super(parent, definition);
|
|
36651
|
-
this.parent = parent;
|
|
36652
|
-
const childrenState = createChildrenState(this);
|
|
36653
|
-
this.childrenState = childrenState;
|
|
36654
|
-
options.precedingPrimaryInstanceNode.after(this.contextNode);
|
|
36655
36809
|
const { precedingInstance } = options;
|
|
36656
36810
|
const precedingIndex = precedingInstance?.currentIndex ?? (() => -1);
|
|
36657
36811
|
const initialIndex = precedingIndex() + 1;
|
|
36658
36812
|
const [currentIndex, setCurrentIndex] = createSignal(initialIndex);
|
|
36813
|
+
super(parent, definition, {
|
|
36814
|
+
computeReference: () => {
|
|
36815
|
+
const currentPosition = currentIndex() + 1;
|
|
36816
|
+
return `${parent.contextReference()}[${currentPosition}]`;
|
|
36817
|
+
}
|
|
36818
|
+
});
|
|
36819
|
+
this.parent = parent;
|
|
36820
|
+
this.appearances = definition.bodyElement.appearances;
|
|
36821
|
+
const childrenState = createChildrenState(this);
|
|
36822
|
+
this.childrenState = childrenState;
|
|
36823
|
+
options.precedingPrimaryInstanceNode.after(this.contextNode);
|
|
36659
36824
|
this.currentIndex = currentIndex;
|
|
36660
36825
|
const state = createSharedNodeState(
|
|
36661
36826
|
this.scope,
|
|
36662
36827
|
{
|
|
36663
|
-
|
|
36828
|
+
reference: this.contextReference,
|
|
36829
|
+
readonly: this.isReadonly,
|
|
36830
|
+
relevant: this.isRelevant,
|
|
36831
|
+
required: this.isRequired,
|
|
36832
|
+
// TODO: only-child <group><label>
|
|
36664
36833
|
label: createNodeLabel(this, definition),
|
|
36665
36834
|
hint: null,
|
|
36666
36835
|
children: childrenState.childIds,
|
|
@@ -36673,7 +36842,11 @@ class RepeatInstance extends DescendantNode {
|
|
|
36673
36842
|
);
|
|
36674
36843
|
this.state = state;
|
|
36675
36844
|
this.engineState = state.engineState;
|
|
36676
|
-
this.currentState = materializeCurrentStateChildren(
|
|
36845
|
+
this.currentState = materializeCurrentStateChildren(
|
|
36846
|
+
this.scope,
|
|
36847
|
+
state.currentState,
|
|
36848
|
+
childrenState
|
|
36849
|
+
);
|
|
36677
36850
|
this.scope.runTask(() => {
|
|
36678
36851
|
const computeCurrentIndex = parent.getInstanceIndex.bind(parent, this);
|
|
36679
36852
|
createComputed(on(computeCurrentIndex, setCurrentIndex, { defer: true }));
|
|
@@ -36685,13 +36858,29 @@ class RepeatInstance extends DescendantNode {
|
|
|
36685
36858
|
// InstanceNode
|
|
36686
36859
|
state;
|
|
36687
36860
|
engineState;
|
|
36861
|
+
/**
|
|
36862
|
+
* A repeat instance can inherit non-relevance, just like any other node. That
|
|
36863
|
+
* inheritance is derived from the repeat instance's parent node in the
|
|
36864
|
+
* primary instance XML/DOM tree (and would be semantically expected to do so
|
|
36865
|
+
* even if we move away from that implementation detail).
|
|
36866
|
+
*
|
|
36867
|
+
* Since {@link RepeatInstance.parent} is a {@link RepeatRange}, which is a
|
|
36868
|
+
* runtime data model fiction that does not exist in that hierarchy, we pass
|
|
36869
|
+
* this call through, allowing the {@link RepeatRange} to check the actual
|
|
36870
|
+
* primary instance parent node's relevance state.
|
|
36871
|
+
*
|
|
36872
|
+
* @todo Should we apply similar reasoning in {@link hasReadonlyAncestor}?
|
|
36873
|
+
*/
|
|
36874
|
+
hasNonRelevantAncestor = () => {
|
|
36875
|
+
return this.parent.hasNonRelevantAncestor();
|
|
36876
|
+
};
|
|
36688
36877
|
// RepeatInstanceNode
|
|
36689
36878
|
nodeType = "repeat-instance";
|
|
36879
|
+
/**
|
|
36880
|
+
* @see {@link RepeatRange.appearances}
|
|
36881
|
+
*/
|
|
36882
|
+
appearances;
|
|
36690
36883
|
currentState;
|
|
36691
|
-
computeReference(parent) {
|
|
36692
|
-
const currentPosition = this.currentIndex() + 1;
|
|
36693
|
-
return `${parent.contextReference}[${currentPosition}]`;
|
|
36694
|
-
}
|
|
36695
36884
|
initializeContextNode(parentContextNode, nodeName) {
|
|
36696
36885
|
return this.createContextNode(parentContextNode, nodeName);
|
|
36697
36886
|
}
|
|
@@ -36755,17 +36944,118 @@ class RepeatRange extends DescendantNode {
|
|
|
36755
36944
|
// InstanceNode
|
|
36756
36945
|
state;
|
|
36757
36946
|
engineState;
|
|
36947
|
+
emptyRangeEvaluationContext;
|
|
36948
|
+
/**
|
|
36949
|
+
* @see {@link isSelfRelevant}
|
|
36950
|
+
*/
|
|
36951
|
+
isEmptyRangeSelfRelevant;
|
|
36952
|
+
/**
|
|
36953
|
+
* A repeat range does not exist in the primary instance tree. A `relevant`
|
|
36954
|
+
* expression applies to each {@link RepeatInstance} child of the repeat
|
|
36955
|
+
* range. Determining whether a repeat range itself "is relevant" isn't a
|
|
36956
|
+
* concept the spec addresses, but it may be used by clients to determine
|
|
36957
|
+
* whether to allow interaction with the range (e.g. by adding a repeat
|
|
36958
|
+
* instance, or presenting the range's label when empty).
|
|
36959
|
+
*
|
|
36960
|
+
* As a naive first pass, it seems like the heuristic for this should be:
|
|
36961
|
+
*
|
|
36962
|
+
* 1. Does the repeat range have any repeat instance children?
|
|
36963
|
+
*
|
|
36964
|
+
* - If yes, go to 2.
|
|
36965
|
+
* - If no, go to 3.
|
|
36966
|
+
*
|
|
36967
|
+
* 2. Does one or more of those children return `true` for the node's
|
|
36968
|
+
* `relevant` expression (i.e. is the repeat instance "self relevant")?
|
|
36969
|
+
*
|
|
36970
|
+
* 3. Does the relevant expression return `true` for the repeat range itself
|
|
36971
|
+
* (where, at least for now, the context of that evaluation would be the
|
|
36972
|
+
* repeat range's {@link anchorNode} to ensure correct relative expressions
|
|
36973
|
+
* resolve correctly)?
|
|
36974
|
+
*
|
|
36975
|
+
* @todo While (3) is proactively implemented, there isn't presently a test
|
|
36976
|
+
* exercising it. It felt best for now to surface this for discussion in
|
|
36977
|
+
* review to validate that it's going in the right direction.
|
|
36978
|
+
*
|
|
36979
|
+
* @todo While (2) **is actually tested**, the tests currently in place behave
|
|
36980
|
+
* the same way with only the logic for (3), regardless of whether the repeat
|
|
36981
|
+
* range actually has any repeat instance children. It's unclear (a) if that's
|
|
36982
|
+
* a preferable simplification and (b) how that might affect performance (in
|
|
36983
|
+
* theory it could vary depending on form structure and runtime state).
|
|
36984
|
+
*/
|
|
36985
|
+
isSelfRelevant = () => {
|
|
36986
|
+
const instances = this.childrenState.getChildren();
|
|
36987
|
+
if (instances.length > 0) {
|
|
36988
|
+
return instances.some((instance) => instance.isSelfRelevant());
|
|
36989
|
+
}
|
|
36990
|
+
return this.isEmptyRangeSelfRelevant();
|
|
36991
|
+
};
|
|
36758
36992
|
// RepeatRangeNode
|
|
36759
36993
|
nodeType = "repeat-range";
|
|
36994
|
+
/**
|
|
36995
|
+
* @todo RepeatRange*, RepeatInstance* (and RepeatTemplate*) all share the
|
|
36996
|
+
* same body element, and thus all share the same definition `bodyElement`. As
|
|
36997
|
+
* such, they also all share the same `appearances`. At time of writing,
|
|
36998
|
+
* `web-forms` (Vue UI package) treats a `RepeatRangeNode`...
|
|
36999
|
+
*
|
|
37000
|
+
* - ... as a group, if the node has a label (i.e.
|
|
37001
|
+
* `<group><label/><repeat/></group>`)
|
|
37002
|
+
* - ... effectively as a fragment containing only its instances, otherwise
|
|
37003
|
+
*
|
|
37004
|
+
* We now collapse `<group><repeat>` into `<repeat>`, and no longer treat
|
|
37005
|
+
* "repeat group" as a concept (after parsing). According to the spec, these
|
|
37006
|
+
* appearances **are supposed to** come from that "repeat group" in the form
|
|
37007
|
+
* definition. In practice, many forms do define appearances directly on a
|
|
37008
|
+
* repeat element. The engine currently produces an error if both are defined
|
|
37009
|
+
* simultaneously, but otherwise makes no distinction between appearances in
|
|
37010
|
+
* these form definition shapes:
|
|
37011
|
+
*
|
|
37012
|
+
* ```xml
|
|
37013
|
+
* <group ref="/data/rep1" appearance="...">
|
|
37014
|
+
* <repeat nodeset="/data/rep1"/>
|
|
37015
|
+
* </group>
|
|
37016
|
+
*
|
|
37017
|
+
* <group ref="/data/rep1">
|
|
37018
|
+
* <repeat nodeset="/data/rep1"/ appearance="...">
|
|
37019
|
+
* </group>
|
|
37020
|
+
*
|
|
37021
|
+
* <repeat nodeset="/data/rep1"/ appearance="...">
|
|
37022
|
+
* ```
|
|
37023
|
+
*
|
|
37024
|
+
* All of the above creates considerable ambiguity about where "repeat
|
|
37025
|
+
* appearances" should apply, under which circumstances.
|
|
37026
|
+
*/
|
|
37027
|
+
appearances;
|
|
36760
37028
|
currentState;
|
|
36761
37029
|
constructor(parent, definition) {
|
|
36762
37030
|
super(parent, definition);
|
|
37031
|
+
this.appearances = definition.bodyElement.appearances;
|
|
36763
37032
|
const childrenState = createChildrenState(this);
|
|
36764
37033
|
this.childrenState = childrenState;
|
|
37034
|
+
this.anchorNode = this.contextNode.ownerDocument.createComment(
|
|
37035
|
+
`Begin repeat range: ${definition.nodeset}`
|
|
37036
|
+
);
|
|
37037
|
+
this.contextNode.append(this.anchorNode);
|
|
37038
|
+
this.emptyRangeEvaluationContext = {
|
|
37039
|
+
scope: this.scope,
|
|
37040
|
+
evaluator: this.evaluator,
|
|
37041
|
+
root: this.root,
|
|
37042
|
+
contextReference: this.contextReference,
|
|
37043
|
+
contextNode: this.anchorNode,
|
|
37044
|
+
getSubscribableDependenciesByReference: (reference) => {
|
|
37045
|
+
return this.getSubscribableDependenciesByReference(reference);
|
|
37046
|
+
}
|
|
37047
|
+
};
|
|
37048
|
+
this.isEmptyRangeSelfRelevant = createComputedExpression(
|
|
37049
|
+
this.emptyRangeEvaluationContext,
|
|
37050
|
+
definition.bind.relevant
|
|
37051
|
+
);
|
|
36765
37052
|
const state = createSharedNodeState(
|
|
36766
37053
|
this.scope,
|
|
36767
37054
|
{
|
|
36768
|
-
|
|
37055
|
+
reference: this.contextReference,
|
|
37056
|
+
readonly: this.isReadonly,
|
|
37057
|
+
relevant: this.isRelevant,
|
|
37058
|
+
required: this.isRequired,
|
|
36769
37059
|
label: createNodeLabel(this, definition),
|
|
36770
37060
|
hint: null,
|
|
36771
37061
|
children: childrenState.childIds,
|
|
@@ -36776,13 +37066,13 @@ class RepeatRange extends DescendantNode {
|
|
|
36776
37066
|
clientStateFactory: this.engineConfig.stateFactory
|
|
36777
37067
|
}
|
|
36778
37068
|
);
|
|
36779
|
-
this.anchorNode = this.contextNode.ownerDocument.createComment(
|
|
36780
|
-
`Begin repeat range: ${definition.nodeset}`
|
|
36781
|
-
);
|
|
36782
|
-
this.contextNode.append(this.anchorNode);
|
|
36783
37069
|
this.state = state;
|
|
36784
37070
|
this.engineState = state.engineState;
|
|
36785
|
-
this.currentState = materializeCurrentStateChildren(
|
|
37071
|
+
this.currentState = materializeCurrentStateChildren(
|
|
37072
|
+
this.scope,
|
|
37073
|
+
state.currentState,
|
|
37074
|
+
childrenState
|
|
37075
|
+
);
|
|
36786
37076
|
definition.instances.forEach((instanceDefinition, index) => {
|
|
36787
37077
|
const afterIndex = index - 1;
|
|
36788
37078
|
this.addInstances(afterIndex, 1, instanceDefinition);
|
|
@@ -36794,9 +37084,6 @@ class RepeatRange extends DescendantNode {
|
|
|
36794
37084
|
initializeContextNode(parentContextNode) {
|
|
36795
37085
|
return parentContextNode;
|
|
36796
37086
|
}
|
|
36797
|
-
computeReference(parent) {
|
|
36798
|
-
return this.computeChildStepReference(parent);
|
|
36799
|
-
}
|
|
36800
37087
|
getInstanceIndex(instance) {
|
|
36801
37088
|
return this.engineState.children.indexOf(instance.nodeId);
|
|
36802
37089
|
}
|
|
@@ -36868,25 +37155,6 @@ class RepeatRange extends DescendantNode {
|
|
|
36868
37155
|
}
|
|
36869
37156
|
}
|
|
36870
37157
|
|
|
36871
|
-
const XML_XPATH_WHITESPACE_SUBPATTERN = "[\\x20\\x09\\x0D\\x0A]";
|
|
36872
|
-
const XML_XPATH_WHITESPACE_PATTERN = new RegExp(XML_XPATH_WHITESPACE_SUBPATTERN, "g");
|
|
36873
|
-
const XML_XPATH_LEADING_TRAILING_WHITESPACE_PATTERN = new RegExp(
|
|
36874
|
-
`^${XML_XPATH_WHITESPACE_SUBPATTERN}+|${XML_XPATH_WHITESPACE_SUBPATTERN}+$`,
|
|
36875
|
-
"g"
|
|
36876
|
-
);
|
|
36877
|
-
const XPATH_REPEATING_WHITESPACE_PATTERN = new RegExp(
|
|
36878
|
-
`${XML_XPATH_WHITESPACE_SUBPATTERN}{2,}`,
|
|
36879
|
-
"g"
|
|
36880
|
-
);
|
|
36881
|
-
const trimXMLXPathWhitespace = (value) => value.replaceAll(XML_XPATH_LEADING_TRAILING_WHITESPACE_PATTERN, "");
|
|
36882
|
-
const normalizeXMLXPathWhitespace = (value) => trimXMLXPathWhitespace(value).replaceAll(XPATH_REPEATING_WHITESPACE_PATTERN, " ");
|
|
36883
|
-
const xmlXPathWhitespaceSeparatedList = (value, options) => {
|
|
36884
|
-
if (value === "") {
|
|
36885
|
-
return [];
|
|
36886
|
-
}
|
|
36887
|
-
return normalizeXMLXPathWhitespace(value).split(XML_XPATH_WHITESPACE_PATTERN);
|
|
36888
|
-
};
|
|
36889
|
-
|
|
36890
37158
|
const createSelectItemLabel = (context, definition) => {
|
|
36891
37159
|
const { label, value } = definition;
|
|
36892
37160
|
return createTextRange(context, "label", label, {
|
|
@@ -36915,15 +37183,14 @@ class ItemsetItemEvaluationContext {
|
|
|
36915
37183
|
this.scope = selectField.scope;
|
|
36916
37184
|
this.evaluator = selectField.evaluator;
|
|
36917
37185
|
this.root = selectField.root;
|
|
37186
|
+
this.contextReference = selectField.contextReference;
|
|
36918
37187
|
}
|
|
36919
37188
|
scope;
|
|
36920
37189
|
evaluator;
|
|
36921
37190
|
root;
|
|
36922
|
-
|
|
36923
|
-
|
|
36924
|
-
|
|
36925
|
-
getSubscribableDependencyByReference(reference) {
|
|
36926
|
-
return this.selectField.getSubscribableDependencyByReference(reference);
|
|
37191
|
+
contextReference;
|
|
37192
|
+
getSubscribableDependenciesByReference(reference) {
|
|
37193
|
+
return this.selectField.getSubscribableDependenciesByReference(reference);
|
|
36927
37194
|
}
|
|
36928
37195
|
}
|
|
36929
37196
|
const createSelectItemsetItemLabel = (context, definition, itemValue) => {
|
|
@@ -36987,7 +37254,7 @@ const createPrimaryInstanceValueState = (context, options) => {
|
|
|
36987
37254
|
const initialValue = initialValueSource === "PRIMARY_INSTANCE" ? contextNode.textContent ?? defaultValue : defaultValue;
|
|
36988
37255
|
const persistedValueState = createSignal(
|
|
36989
37256
|
{
|
|
36990
|
-
isRelevant: context.isRelevant,
|
|
37257
|
+
isRelevant: context.isRelevant(),
|
|
36991
37258
|
value: initialValue
|
|
36992
37259
|
},
|
|
36993
37260
|
{
|
|
@@ -37004,7 +37271,7 @@ const createPrimaryInstanceValueState = (context, options) => {
|
|
|
37004
37271
|
);
|
|
37005
37272
|
const [persistedValue, setValueForPersistence] = persistedValueState;
|
|
37006
37273
|
createComputed(() => {
|
|
37007
|
-
const isRelevant = context.isRelevant;
|
|
37274
|
+
const isRelevant = context.isRelevant();
|
|
37008
37275
|
setValueForPersistence((persisted) => {
|
|
37009
37276
|
return {
|
|
37010
37277
|
isRelevant,
|
|
@@ -37027,7 +37294,7 @@ const createPrimaryInstanceValueState = (context, options) => {
|
|
|
37027
37294
|
});
|
|
37028
37295
|
const setPrimaryInstanceValue = (value) => {
|
|
37029
37296
|
const persisted = setValueForPersistence({
|
|
37030
|
-
isRelevant: context.isRelevant,
|
|
37297
|
+
isRelevant: context.isRelevant(),
|
|
37031
37298
|
value
|
|
37032
37299
|
});
|
|
37033
37300
|
return persisted.value;
|
|
@@ -37056,8 +37323,8 @@ const guardDownstreamReadonlyWrites = (context, baseState) => {
|
|
|
37056
37323
|
}
|
|
37057
37324
|
const [getValue, baseSetValue] = baseState;
|
|
37058
37325
|
const setValue = (value) => {
|
|
37059
|
-
if (context.isReadonly) {
|
|
37060
|
-
const reference = untrack(() => context.contextReference);
|
|
37326
|
+
if (context.isReadonly()) {
|
|
37327
|
+
const reference = untrack(() => context.contextReference());
|
|
37061
37328
|
throw new Error(`Cannot write to readonly field: ${reference}`);
|
|
37062
37329
|
}
|
|
37063
37330
|
return baseSetValue(value);
|
|
@@ -37068,7 +37335,7 @@ const createCalculation = (context, setValue, calculateDefinition) => {
|
|
|
37068
37335
|
context.scope.runTask(() => {
|
|
37069
37336
|
const calculate = createComputedExpression(context, calculateDefinition);
|
|
37070
37337
|
createComputed(() => {
|
|
37071
|
-
if (context.isRelevant) {
|
|
37338
|
+
if (context.isRelevant()) {
|
|
37072
37339
|
const calculated = calculate();
|
|
37073
37340
|
const value = context.decodeValue(calculated);
|
|
37074
37341
|
setValue(value);
|
|
@@ -37101,6 +37368,7 @@ class SelectField extends DescendantNode {
|
|
|
37101
37368
|
engineState;
|
|
37102
37369
|
// SelectNode
|
|
37103
37370
|
nodeType = "select";
|
|
37371
|
+
appearances;
|
|
37104
37372
|
currentState;
|
|
37105
37373
|
// ValueContext
|
|
37106
37374
|
encodeValue = (runtimeValue) => {
|
|
@@ -37109,7 +37377,9 @@ class SelectField extends DescendantNode {
|
|
|
37109
37377
|
};
|
|
37110
37378
|
decodeValue = (instanceValue) => {
|
|
37111
37379
|
return this.scope.runTask(() => {
|
|
37112
|
-
const values = xmlXPathWhitespaceSeparatedList(instanceValue
|
|
37380
|
+
const values = xmlXPathWhitespaceSeparatedList(instanceValue, {
|
|
37381
|
+
ignoreEmpty: true
|
|
37382
|
+
});
|
|
37113
37383
|
const items = this.getSelectItemsByValue();
|
|
37114
37384
|
return values.map((value) => {
|
|
37115
37385
|
return items.get(value);
|
|
@@ -37121,13 +37391,17 @@ class SelectField extends DescendantNode {
|
|
|
37121
37391
|
getValueOptions;
|
|
37122
37392
|
constructor(parent, definition) {
|
|
37123
37393
|
super(parent, definition);
|
|
37394
|
+
this.appearances = definition.bodyElement.appearances;
|
|
37124
37395
|
this.selectExclusive = definition.bodyElement.type === "select1";
|
|
37125
37396
|
const valueOptions = createSelectItems(this);
|
|
37126
37397
|
this.getValueOptions = valueOptions;
|
|
37127
37398
|
const state = createSharedNodeState(
|
|
37128
37399
|
this.scope,
|
|
37129
37400
|
{
|
|
37130
|
-
|
|
37401
|
+
reference: this.contextReference,
|
|
37402
|
+
readonly: this.isReadonly,
|
|
37403
|
+
relevant: this.isRelevant,
|
|
37404
|
+
required: this.isRequired,
|
|
37131
37405
|
label: createNodeLabel(this, definition),
|
|
37132
37406
|
hint: createFieldHint(this, definition),
|
|
37133
37407
|
children: null,
|
|
@@ -37149,9 +37423,6 @@ class SelectField extends DescendantNode {
|
|
|
37149
37423
|
})
|
|
37150
37424
|
);
|
|
37151
37425
|
}
|
|
37152
|
-
computeReference(parent) {
|
|
37153
|
-
return this.computeChildStepReference(parent);
|
|
37154
|
-
}
|
|
37155
37426
|
updateSelectedItemValues(values) {
|
|
37156
37427
|
const itemsByValue = untrack(() => this.getSelectItemsByValue());
|
|
37157
37428
|
const items = values.flatMap((value) => {
|
|
@@ -37214,16 +37485,21 @@ class StringField extends DescendantNode {
|
|
|
37214
37485
|
engineState;
|
|
37215
37486
|
// StringNode
|
|
37216
37487
|
nodeType = "string";
|
|
37488
|
+
appearances;
|
|
37217
37489
|
currentState;
|
|
37218
37490
|
// ValueContext
|
|
37219
37491
|
encodeValue = identity$1;
|
|
37220
37492
|
decodeValue = identity$1;
|
|
37221
37493
|
constructor(parent, definition) {
|
|
37222
37494
|
super(parent, definition);
|
|
37495
|
+
this.appearances = definition.bodyElement?.appearances ?? null;
|
|
37223
37496
|
const state = createSharedNodeState(
|
|
37224
37497
|
this.scope,
|
|
37225
37498
|
{
|
|
37226
|
-
|
|
37499
|
+
reference: this.contextReference,
|
|
37500
|
+
readonly: this.isReadonly,
|
|
37501
|
+
relevant: this.isRelevant,
|
|
37502
|
+
required: this.isRequired,
|
|
37227
37503
|
label: createNodeLabel(this, definition),
|
|
37228
37504
|
hint: createFieldHint(this, definition),
|
|
37229
37505
|
children: null,
|
|
@@ -37238,9 +37514,6 @@ class StringField extends DescendantNode {
|
|
|
37238
37514
|
this.engineState = state.engineState;
|
|
37239
37515
|
this.currentState = state.currentState;
|
|
37240
37516
|
}
|
|
37241
|
-
computeReference(parent) {
|
|
37242
|
-
return this.computeChildStepReference(parent);
|
|
37243
|
-
}
|
|
37244
37517
|
// InstanceNode
|
|
37245
37518
|
getChildren() {
|
|
37246
37519
|
return [];
|
|
@@ -37259,6 +37532,7 @@ class Subtree extends DescendantNode {
|
|
|
37259
37532
|
engineState;
|
|
37260
37533
|
// SubtreeNode
|
|
37261
37534
|
nodeType = "subtree";
|
|
37535
|
+
appearances = null;
|
|
37262
37536
|
currentState;
|
|
37263
37537
|
constructor(parent, definition) {
|
|
37264
37538
|
super(parent, definition);
|
|
@@ -37267,7 +37541,10 @@ class Subtree extends DescendantNode {
|
|
|
37267
37541
|
const state = createSharedNodeState(
|
|
37268
37542
|
this.scope,
|
|
37269
37543
|
{
|
|
37270
|
-
|
|
37544
|
+
reference: this.contextReference,
|
|
37545
|
+
readonly: this.isReadonly,
|
|
37546
|
+
relevant: this.isRelevant,
|
|
37547
|
+
required: this.isRequired,
|
|
37271
37548
|
label: null,
|
|
37272
37549
|
hint: null,
|
|
37273
37550
|
children: childrenState.childIds,
|
|
@@ -37280,12 +37557,13 @@ class Subtree extends DescendantNode {
|
|
|
37280
37557
|
);
|
|
37281
37558
|
this.state = state;
|
|
37282
37559
|
this.engineState = state.engineState;
|
|
37283
|
-
this.currentState = materializeCurrentStateChildren(
|
|
37560
|
+
this.currentState = materializeCurrentStateChildren(
|
|
37561
|
+
this.scope,
|
|
37562
|
+
state.currentState,
|
|
37563
|
+
childrenState
|
|
37564
|
+
);
|
|
37284
37565
|
childrenState.setChildren(buildChildren(this));
|
|
37285
37566
|
}
|
|
37286
|
-
computeReference(parent) {
|
|
37287
|
-
return this.computeChildStepReference(parent);
|
|
37288
|
-
}
|
|
37289
37567
|
getChildren() {
|
|
37290
37568
|
return this.childrenState.getChildren();
|
|
37291
37569
|
}
|
|
@@ -37304,14 +37582,20 @@ const buildChildren = (parent) => {
|
|
|
37304
37582
|
}
|
|
37305
37583
|
return new Group(parent, child);
|
|
37306
37584
|
}
|
|
37307
|
-
case "repeat-
|
|
37585
|
+
case "repeat-range": {
|
|
37308
37586
|
return new RepeatRange(parent, child);
|
|
37309
37587
|
}
|
|
37310
37588
|
case "value-node": {
|
|
37311
|
-
|
|
37312
|
-
|
|
37589
|
+
switch (child.bodyElement?.type) {
|
|
37590
|
+
case "select":
|
|
37591
|
+
case "select1":
|
|
37592
|
+
return new SelectField(parent, child);
|
|
37593
|
+
case "input":
|
|
37594
|
+
case void 0:
|
|
37595
|
+
return new StringField(parent, child);
|
|
37596
|
+
default:
|
|
37597
|
+
throw new UnreachableError(child.bodyElement);
|
|
37313
37598
|
}
|
|
37314
|
-
return new StringField(parent, child);
|
|
37315
37599
|
}
|
|
37316
37600
|
default: {
|
|
37317
37601
|
throw new UnreachableError(child);
|
|
@@ -37350,27 +37634,24 @@ const getInitialLanguageState = (translations) => {
|
|
|
37350
37634
|
};
|
|
37351
37635
|
};
|
|
37352
37636
|
class Root extends InstanceNode {
|
|
37353
|
-
static async initialize(xformDOM, definition, engineConfig) {
|
|
37354
|
-
const instance = new Root(xformDOM, definition, engineConfig);
|
|
37355
|
-
await instance.formStateInitialized();
|
|
37356
|
-
return instance;
|
|
37357
|
-
}
|
|
37358
37637
|
childrenState;
|
|
37359
37638
|
// InstanceNode
|
|
37639
|
+
hasReadonlyAncestor = () => false;
|
|
37640
|
+
isReadonly = () => false;
|
|
37641
|
+
hasNonRelevantAncestor = () => false;
|
|
37642
|
+
isRelevant = () => true;
|
|
37360
37643
|
state;
|
|
37361
37644
|
engineState;
|
|
37362
37645
|
// RootNode
|
|
37363
37646
|
nodeType = "root";
|
|
37647
|
+
appearances = null;
|
|
37648
|
+
classes;
|
|
37364
37649
|
currentState;
|
|
37365
37650
|
instanceDOM;
|
|
37366
37651
|
// BaseNode
|
|
37367
37652
|
root = this;
|
|
37368
37653
|
// EvaluationContext
|
|
37369
37654
|
evaluator;
|
|
37370
|
-
rootReference;
|
|
37371
|
-
get contextReference() {
|
|
37372
|
-
return this.rootReference;
|
|
37373
|
-
}
|
|
37374
37655
|
contextNode;
|
|
37375
37656
|
// RootNode
|
|
37376
37657
|
parent = null;
|
|
@@ -37380,11 +37661,13 @@ class Root extends InstanceNode {
|
|
|
37380
37661
|
return this.engineState.activeLanguage;
|
|
37381
37662
|
}
|
|
37382
37663
|
constructor(xformDOM, definition, engineConfig) {
|
|
37383
|
-
|
|
37664
|
+
const reference = definition.nodeset;
|
|
37665
|
+
super(engineConfig, null, definition, {
|
|
37666
|
+
computeReference: () => reference
|
|
37667
|
+
});
|
|
37668
|
+
this.classes = definition.classes;
|
|
37384
37669
|
const childrenState = createChildrenState(this);
|
|
37385
37670
|
this.childrenState = childrenState;
|
|
37386
|
-
const reference = definition.nodeset;
|
|
37387
|
-
this.rootReference = reference;
|
|
37388
37671
|
const instanceDOM = xformDOM.createInstance();
|
|
37389
37672
|
const evaluator = instanceDOM.primaryInstanceEvaluator;
|
|
37390
37673
|
const { translations } = evaluator;
|
|
@@ -37409,7 +37692,11 @@ class Root extends InstanceNode {
|
|
|
37409
37692
|
);
|
|
37410
37693
|
this.state = state;
|
|
37411
37694
|
this.engineState = state.engineState;
|
|
37412
|
-
this.currentState = materializeCurrentStateChildren(
|
|
37695
|
+
this.currentState = materializeCurrentStateChildren(
|
|
37696
|
+
this.scope,
|
|
37697
|
+
state.currentState,
|
|
37698
|
+
childrenState
|
|
37699
|
+
);
|
|
37413
37700
|
const contextNode = instanceDOM.xformDocument.createElement(definition.nodeName);
|
|
37414
37701
|
instanceDOM.primaryInstanceRoot.replaceWith(contextNode);
|
|
37415
37702
|
this.evaluator = evaluator;
|
|
@@ -37418,37 +37705,6 @@ class Root extends InstanceNode {
|
|
|
37418
37705
|
this.languages = languages;
|
|
37419
37706
|
childrenState.setChildren(buildChildren(this));
|
|
37420
37707
|
}
|
|
37421
|
-
/**
|
|
37422
|
-
* Waits until form state is fully initialized.
|
|
37423
|
-
*
|
|
37424
|
-
* As much as possible, all instance state computations are implemented so
|
|
37425
|
-
* that they complete synchronously.
|
|
37426
|
-
*
|
|
37427
|
-
* There is currently one exception: because instance nodes may form
|
|
37428
|
-
* computation dependencies into their descendants as well as their ancestors,
|
|
37429
|
-
* there is an allowance **during form initialization only** to account for
|
|
37430
|
-
* this chicken/egg scenario. Note that this allowance is intentionally,
|
|
37431
|
-
* strictly limited: if form state initialization is not resolved within a
|
|
37432
|
-
* single microtask tick we throw/reject.
|
|
37433
|
-
*
|
|
37434
|
-
* All subsequent computations are always performed synchronously (and we will
|
|
37435
|
-
* use tests to validate this, by utilizing the synchronously returned `Root`
|
|
37436
|
-
* state from client-facing write interfaces).
|
|
37437
|
-
*/
|
|
37438
|
-
async formStateInitialized() {
|
|
37439
|
-
await new Promise((resolve) => {
|
|
37440
|
-
queueMicrotask(resolve);
|
|
37441
|
-
});
|
|
37442
|
-
if (!this.isStateInitialized()) {
|
|
37443
|
-
throw new Error(
|
|
37444
|
-
"Form state initialization failed to complete in a single frame. Has some aspect of reactive computation been made asynchronous by mistake?"
|
|
37445
|
-
);
|
|
37446
|
-
}
|
|
37447
|
-
}
|
|
37448
|
-
// InstanceNode
|
|
37449
|
-
computeReference(_parent, definition) {
|
|
37450
|
-
return definition.nodeset;
|
|
37451
|
-
}
|
|
37452
37708
|
getChildren() {
|
|
37453
37709
|
return this.childrenState.getChildren();
|
|
37454
37710
|
}
|
|
@@ -37482,7 +37738,7 @@ const initializeForm$1 = async (input, options = {}) => {
|
|
|
37482
37738
|
const engineConfig = buildInstanceConfig(options.config);
|
|
37483
37739
|
const sourceXML = await retrieveSourceXMLResource(input, engineConfig);
|
|
37484
37740
|
const form = new XFormDefinition(sourceXML);
|
|
37485
|
-
return Root
|
|
37741
|
+
return new Root(form.xformDOM, form.model.root, engineConfig);
|
|
37486
37742
|
};
|
|
37487
37743
|
|
|
37488
37744
|
const initializeForm = initializeForm$1;
|