@getodk/xforms-engine 0.16.0 → 0.17.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/client/AttributeNode.d.ts +4 -3
- package/dist/client/InputNode.d.ts +8 -4
- package/dist/client/MarkdownNode.d.ts +3 -0
- package/dist/client/NoteNode.d.ts +6 -2
- package/dist/client/form/FormInstanceConfig.d.ts +4 -0
- package/dist/client/form/LoadFormResult.d.ts +5 -14
- package/dist/client/form/ResetFormInstance.d.ts +13 -0
- package/dist/entrypoints/FormResult/BaseFormResult.d.ts +1 -0
- package/dist/entrypoints/FormResult/BaseInstantiableFormResult.d.ts +2 -0
- package/dist/entrypoints/FormResult/FormFailureResult.d.ts +2 -0
- package/dist/entrypoints/createPotentiallyClientOwnedReactiveScope.d.ts +19 -0
- package/dist/index.js +22150 -25908
- package/dist/index.js.map +1 -1
- package/dist/instance/Attribute.d.ts +11 -23
- package/dist/instance/Group.d.ts +3 -0
- package/dist/instance/InputControl.d.ts +3 -0
- package/dist/instance/ModelValue.d.ts +4 -0
- package/dist/instance/Note.d.ts +4 -0
- package/dist/instance/PrimaryInstance.d.ts +7 -1
- package/dist/instance/RangeControl.d.ts +4 -0
- package/dist/instance/RankControl.d.ts +5 -1
- package/dist/instance/Root.d.ts +3 -0
- package/dist/instance/SelectControl.d.ts +5 -1
- package/dist/instance/TriggerControl.d.ts +4 -0
- package/dist/instance/UploadControl.d.ts +3 -0
- package/dist/instance/abstract/DescendantNode.d.ts +5 -4
- package/dist/instance/abstract/InstanceNode.d.ts +4 -3
- package/dist/instance/hierarchy.d.ts +2 -1
- package/dist/instance/internal-api/AttributeContext.d.ts +1 -0
- package/dist/instance/internal-api/InstanceConfig.d.ts +2 -1
- package/dist/instance/internal-api/InstanceValueContext.d.ts +1 -0
- package/dist/instance/markdown/MarkdownNode.d.ts +14 -9
- package/dist/instance/repeat/RepeatInstance.d.ts +2 -0
- package/dist/integration/xpath/adapter/XFormsXPathNode.d.ts +1 -1
- package/dist/integration/xpath/adapter/kind.d.ts +5 -3
- package/dist/integration/xpath/adapter/traversal.d.ts +3 -3
- package/dist/integration/xpath/static-dom/StaticAttribute.d.ts +1 -0
- package/dist/integration/xpath/static-dom/StaticDocument.d.ts +2 -0
- package/dist/lib/codecs/{Geopoint/Geopoint.d.ts → geolocation/Geolocation.d.ts} +11 -15
- package/dist/lib/codecs/geolocation/Geopoint.d.ts +7 -0
- package/dist/lib/codecs/geolocation/Geoshape.d.ts +7 -0
- package/dist/lib/codecs/geolocation/Geotrace.d.ts +7 -0
- package/dist/lib/codecs/geolocation/createGeolocationValueCodec.d.ts +3 -0
- package/dist/lib/codecs/getSharedValueCodec.d.ts +7 -5
- package/dist/lib/reactivity/text/createTextRange.d.ts +0 -2
- package/dist/parse/XFormDOM.d.ts +7 -1
- package/dist/parse/body/appearance/inputAppearanceParser.d.ts +1 -1
- package/dist/parse/model/ActionDefinition.d.ts +1 -1
- package/dist/parse/model/AttributeDefinition.d.ts +2 -0
- package/dist/parse/model/BindPreloadDefinition.d.ts +2 -1
- package/dist/parse/model/ModelActionMap.d.ts +3 -2
- package/dist/parse/model/ModelDefinition.d.ts +3 -5
- package/dist/parse/model/SecondaryInstance/sources/CSVExternalSecondaryInstance.d.ts +0 -17
- package/dist/parse/model/SecondaryInstance/sources/external-instance-csv-parser.d.ts +8 -0
- package/dist/parse/model/TranslationDefinitionMap.d.ts +4 -0
- package/dist/solid.js +21608 -25366
- package/dist/solid.js.map +1 -1
- package/package.json +2 -2
- package/src/client/AttributeNode.ts +4 -3
- package/src/client/InputNode.ts +11 -3
- package/src/client/MarkdownNode.ts +3 -0
- package/src/client/NoteNode.ts +9 -1
- package/src/client/form/FormInstanceConfig.ts +6 -0
- package/src/client/form/LoadFormResult.ts +5 -17
- package/src/client/form/ResetFormInstance.ts +17 -0
- package/src/entrypoints/FormInstance.ts +2 -0
- package/src/entrypoints/FormResult/BaseFormResult.ts +1 -0
- package/src/entrypoints/FormResult/BaseInstantiableFormResult.ts +10 -1
- package/src/entrypoints/FormResult/FormFailureResult.ts +3 -0
- package/src/entrypoints/createPotentiallyClientOwnedReactiveScope.ts +30 -0
- package/src/entrypoints/loadForm.ts +1 -31
- package/src/instance/Attribute.ts +38 -54
- package/src/instance/Group.ts +12 -4
- package/src/instance/InputControl.ts +15 -9
- package/src/instance/ModelValue.ts +13 -4
- package/src/instance/Note.ts +13 -4
- package/src/instance/PrimaryInstance.ts +29 -6
- package/src/instance/RangeControl.ts +13 -4
- package/src/instance/RankControl.ts +14 -5
- package/src/instance/Root.ts +12 -4
- package/src/instance/SelectControl.ts +14 -5
- package/src/instance/TriggerControl.ts +13 -4
- package/src/instance/UploadControl.ts +13 -3
- package/src/instance/abstract/DescendantNode.ts +4 -3
- package/src/instance/abstract/InstanceNode.ts +5 -3
- package/src/instance/attachments/buildAttributes.ts +26 -2
- package/src/instance/children/childrenInitOptions.ts +2 -1
- package/src/instance/hierarchy.ts +2 -0
- package/src/instance/internal-api/AttributeContext.ts +1 -0
- package/src/instance/internal-api/InstanceConfig.ts +3 -0
- package/src/instance/internal-api/InstanceValueContext.ts +1 -0
- package/src/instance/markdown/MarkdownNode.ts +19 -7
- package/src/instance/repeat/RepeatInstance.ts +11 -3
- package/src/instance/text/markdownFormat.ts +4 -3
- package/src/integration/xpath/adapter/XFormsXPathNode.ts +1 -0
- package/src/integration/xpath/adapter/engineDOMAdapter.ts +2 -2
- package/src/integration/xpath/adapter/kind.ts +6 -1
- package/src/integration/xpath/adapter/names.ts +1 -0
- package/src/integration/xpath/adapter/traversal.ts +5 -6
- package/src/integration/xpath/static-dom/StaticAttribute.ts +1 -0
- package/src/integration/xpath/static-dom/StaticDocument.ts +2 -0
- package/src/lib/codecs/{Geopoint/Geopoint.ts → geolocation/Geolocation.ts} +43 -24
- package/src/lib/codecs/geolocation/Geopoint.ts +15 -0
- package/src/lib/codecs/geolocation/Geoshape.ts +36 -0
- package/src/lib/codecs/geolocation/Geotrace.ts +36 -0
- package/src/lib/codecs/geolocation/createGeolocationValueCodec.ts +18 -0
- package/src/lib/codecs/getSharedValueCodec.ts +37 -11
- package/src/lib/reactivity/createInstanceValueState.ts +90 -34
- package/src/lib/reactivity/text/createTextRange.ts +71 -45
- package/src/parse/XFormDOM.ts +22 -2
- package/src/parse/model/ActionDefinition.ts +6 -6
- package/src/parse/model/AttributeDefinition.ts +7 -0
- package/src/parse/model/BindDefinition.ts +1 -1
- package/src/parse/model/BindPreloadDefinition.ts +21 -14
- package/src/parse/model/ModelActionMap.ts +30 -13
- package/src/parse/model/ModelDefinition.ts +5 -10
- package/src/parse/model/RootDefinition.ts +2 -1
- package/src/parse/model/SecondaryInstance/sources/CSVExternalSecondaryInstance.ts +2 -184
- package/src/parse/model/SecondaryInstance/sources/external-instance-csv-parser.ts +185 -0
- package/src/parse/model/TranslationDefinitionMap.ts +23 -0
- package/dist/lib/codecs/Geopoint/GeopointValueCodec.d.ts +0 -5
- package/dist/parse/model/generateItextChunks.d.ts +0 -5
- package/src/lib/codecs/Geopoint/GeopointValueCodec.ts +0 -20
- package/src/parse/model/generateItextChunks.ts +0 -61
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getodk/xforms-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "XForms engine for ODK Web Forms",
|
|
6
6
|
"type": "module",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@babel/core": "^7.28.5",
|
|
65
65
|
"@getodk/tree-sitter-xpath": "0.2.2",
|
|
66
|
-
"@getodk/xpath": "0.
|
|
66
|
+
"@getodk/xpath": "0.10.0",
|
|
67
67
|
"@playwright/test": "^1.57.0",
|
|
68
68
|
"@types/papaparse": "^5.5.0",
|
|
69
69
|
"@vitest/browser": "^3.2.4",
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { Root } from '../instance/Root.ts';
|
|
2
2
|
import type { AttributeDefinition } from '../parse/model/AttributeDefinition.ts';
|
|
3
|
+
import type { BaseNode, BaseNodeState } from './BaseNode.ts';
|
|
3
4
|
import type { OpaqueReactiveObjectFactory } from './OpaqueReactiveObjectFactory.ts';
|
|
4
5
|
import type { InstanceState } from './serialization/InstanceState.ts';
|
|
5
6
|
|
|
6
|
-
export interface AttributeNodeState {
|
|
7
|
+
export interface AttributeNodeState extends BaseNodeState {
|
|
7
8
|
get value(): string;
|
|
8
9
|
get relevant(): boolean;
|
|
9
10
|
}
|
|
@@ -11,7 +12,7 @@ export interface AttributeNodeState {
|
|
|
11
12
|
/**
|
|
12
13
|
* Base interface for common/shared aspects of attributes.
|
|
13
14
|
*/
|
|
14
|
-
export interface AttributeNode {
|
|
15
|
+
export interface AttributeNode extends BaseNode {
|
|
15
16
|
/**
|
|
16
17
|
* Specifies the node's general type. This can be useful for narrowing types,
|
|
17
18
|
* e.g. those of children.
|
|
@@ -31,7 +32,7 @@ export interface AttributeNode {
|
|
|
31
32
|
*/
|
|
32
33
|
readonly root: Root;
|
|
33
34
|
|
|
34
|
-
readonly
|
|
35
|
+
readonly parent: unknown;
|
|
35
36
|
|
|
36
37
|
/**
|
|
37
38
|
* Each node provides a discrete object representing the stateful aspects of
|
package/src/client/InputNode.ts
CHANGED
|
@@ -49,8 +49,8 @@ interface InputNodeOptionsByValueType {
|
|
|
49
49
|
readonly time: null;
|
|
50
50
|
readonly dateTime: null;
|
|
51
51
|
readonly geopoint: GeoInputNodeOptions;
|
|
52
|
-
readonly geotrace:
|
|
53
|
-
readonly geoshape:
|
|
52
|
+
readonly geotrace: null;
|
|
53
|
+
readonly geoshape: null;
|
|
54
54
|
readonly binary: null;
|
|
55
55
|
readonly barcode: null;
|
|
56
56
|
readonly intent: null;
|
|
@@ -86,12 +86,16 @@ export type IntInputValue = InputValue<'int'>;
|
|
|
86
86
|
export type DecimalInputValue = InputValue<'decimal'>;
|
|
87
87
|
export type DateInputValue = InputValue<'date'>;
|
|
88
88
|
export type GeopointInputValue = InputValue<'geopoint'>;
|
|
89
|
+
export type GeoshapeInputValue = InputValue<'geoshape'>;
|
|
90
|
+
export type GeotraceInputValue = InputValue<'geotrace'>;
|
|
89
91
|
|
|
90
92
|
export type StringInputNode = InputNode<'string'>;
|
|
91
93
|
export type IntInputNode = InputNode<'int'>;
|
|
92
94
|
export type DecimalInputNode = InputNode<'decimal'>;
|
|
93
95
|
export type DateInputNode = InputNode<'date'>;
|
|
94
96
|
export type GeopointInputNode = InputNode<'geopoint'>;
|
|
97
|
+
export type GeoshapeInputNode = InputNode<'geoshape'>;
|
|
98
|
+
export type GeotraceInputNode = InputNode<'geotrace'>;
|
|
95
99
|
|
|
96
100
|
// prettier-ignore
|
|
97
101
|
type SupportedInputValueType =
|
|
@@ -100,7 +104,9 @@ type SupportedInputValueType =
|
|
|
100
104
|
| 'int'
|
|
101
105
|
| 'decimal'
|
|
102
106
|
| 'date'
|
|
103
|
-
| 'geopoint'
|
|
107
|
+
| 'geopoint'
|
|
108
|
+
| 'geoshape'
|
|
109
|
+
| 'geotrace';
|
|
104
110
|
|
|
105
111
|
type TemporaryStringValueType = Exclude<ValueType, SupportedInputValueType>;
|
|
106
112
|
|
|
@@ -114,4 +120,6 @@ export type AnyInputNode =
|
|
|
114
120
|
| DecimalInputNode
|
|
115
121
|
| DateInputNode
|
|
116
122
|
| GeopointInputNode
|
|
123
|
+
| GeoshapeInputNode
|
|
124
|
+
| GeotraceInputNode
|
|
117
125
|
| TemporaryStringValueInputNode;
|
|
@@ -16,17 +16,20 @@ export type ElementName =
|
|
|
16
16
|
export type MarkdownNode = ChildMarkdownNode | HtmlMarkdownNode | ParentMarkdownNode;
|
|
17
17
|
|
|
18
18
|
export interface ParentMarkdownNode {
|
|
19
|
+
readonly id: string;
|
|
19
20
|
readonly role: 'parent';
|
|
20
21
|
readonly elementName: string;
|
|
21
22
|
readonly children: MarkdownNode[];
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
export interface ChildMarkdownNode {
|
|
26
|
+
readonly id: string;
|
|
25
27
|
readonly role: 'child';
|
|
26
28
|
readonly value: string;
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
export interface HtmlMarkdownNode {
|
|
32
|
+
readonly id: string;
|
|
30
33
|
readonly role: 'html';
|
|
31
34
|
readonly unsafeHtml: string;
|
|
32
35
|
}
|
package/src/client/NoteNode.ts
CHANGED
|
@@ -83,12 +83,16 @@ export type IntNoteValue = NoteValue<'int'>;
|
|
|
83
83
|
export type DecimalNoteValue = NoteValue<'decimal'>;
|
|
84
84
|
export type DateNoteValue = NoteValue<'date'>;
|
|
85
85
|
export type GeopointNoteValue = NoteValue<'geopoint'>;
|
|
86
|
+
export type GeoshapeNoteValue = NoteValue<'geoshape'>;
|
|
87
|
+
export type GeotraceNoteValue = NoteValue<'geotrace'>;
|
|
86
88
|
|
|
87
89
|
export type StringNoteNode = NoteNode<'string'>;
|
|
88
90
|
export type IntNoteNode = NoteNode<'int'>;
|
|
89
91
|
export type DecimalNoteNode = NoteNode<'decimal'>;
|
|
90
92
|
export type DateNoteNode = NoteNode<'date'>;
|
|
91
93
|
export type GeopointNoteNode = NoteNode<'geopoint'>;
|
|
94
|
+
export type GeoshapeNoteNode = NoteNode<'geoshape'>;
|
|
95
|
+
export type GeotraceNoteNode = NoteNode<'geotrace'>;
|
|
92
96
|
|
|
93
97
|
// prettier-ignore
|
|
94
98
|
type SupportedNoteValueType =
|
|
@@ -97,7 +101,9 @@ type SupportedNoteValueType =
|
|
|
97
101
|
| 'int'
|
|
98
102
|
| 'decimal'
|
|
99
103
|
| 'date'
|
|
100
|
-
| 'geopoint'
|
|
104
|
+
| 'geopoint'
|
|
105
|
+
| 'geoshape'
|
|
106
|
+
| 'geotrace';
|
|
101
107
|
|
|
102
108
|
type TemporaryStringValueType = Exclude<ValueType, SupportedNoteValueType>;
|
|
103
109
|
|
|
@@ -111,4 +117,6 @@ export type AnyNoteNode =
|
|
|
111
117
|
| DecimalNoteNode
|
|
112
118
|
| DateNoteNode
|
|
113
119
|
| GeopointNoteNode
|
|
120
|
+
| GeoshapeNoteNode
|
|
121
|
+
| GeotraceNoteNode
|
|
114
122
|
| TemporaryStringValueNoteNode;
|
|
@@ -16,6 +16,10 @@ export interface PreloadProperties {
|
|
|
16
16
|
readonly phoneNumber?: string;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
export interface GeolocationProvider {
|
|
20
|
+
getLocation(): Promise<string>;
|
|
21
|
+
}
|
|
22
|
+
|
|
19
23
|
export interface FormInstanceConfig {
|
|
20
24
|
/**
|
|
21
25
|
* A client may specify a generic function for constructing stateful objects.
|
|
@@ -35,4 +39,6 @@ export interface FormInstanceConfig {
|
|
|
35
39
|
readonly instanceAttachments?: InstanceAttachmentsConfig;
|
|
36
40
|
|
|
37
41
|
readonly preloadProperties?: PreloadProperties;
|
|
42
|
+
|
|
43
|
+
readonly geolocationProvider?: GeolocationProvider;
|
|
38
44
|
}
|
|
@@ -3,6 +3,7 @@ import type { AnyFunction } from '@getodk/common/types/helpers.js';
|
|
|
3
3
|
import type { LoadFormFailureError } from '../../error/LoadFormFailureError.ts';
|
|
4
4
|
import type { CreateFormInstance } from './CreateFormInstance.ts';
|
|
5
5
|
import type { EditFormInstance } from './EditFormInstance.ts';
|
|
6
|
+
import type { ResetFormInstance } from './ResetFormInstance.ts';
|
|
6
7
|
import type { RestoreFormInstance } from './RestoreFormInstance.ts';
|
|
7
8
|
|
|
8
9
|
// Re-export for client access
|
|
@@ -44,6 +45,7 @@ interface BaseLoadFormResult {
|
|
|
44
45
|
readonly warnings: LoadFormWarnings | null;
|
|
45
46
|
readonly error: LoadFormFailureError | null;
|
|
46
47
|
readonly createInstance: FallibleLoadFormResultMethod<CreateFormInstance>;
|
|
48
|
+
readonly resetInstance: FallibleLoadFormResultMethod<ResetFormInstance>;
|
|
47
49
|
readonly editInstance: FallibleLoadFormResultMethod<EditFormInstance>;
|
|
48
50
|
readonly restoreInstance: FallibleLoadFormResultMethod<RestoreFormInstance>;
|
|
49
51
|
}
|
|
@@ -53,6 +55,7 @@ export interface LoadFormSuccessResult extends BaseLoadFormResult {
|
|
|
53
55
|
readonly warnings: null;
|
|
54
56
|
readonly error: null;
|
|
55
57
|
readonly createInstance: CreateFormInstance;
|
|
58
|
+
readonly resetInstance: ResetFormInstance;
|
|
56
59
|
readonly editInstance: EditFormInstance;
|
|
57
60
|
readonly restoreInstance: RestoreFormInstance;
|
|
58
61
|
}
|
|
@@ -62,6 +65,7 @@ export interface LoadFormWarningResult extends BaseLoadFormResult {
|
|
|
62
65
|
readonly warnings: LoadFormWarnings;
|
|
63
66
|
readonly error: null;
|
|
64
67
|
readonly createInstance: CreateFormInstance;
|
|
68
|
+
readonly resetInstance: ResetFormInstance;
|
|
65
69
|
readonly editInstance: EditFormInstance;
|
|
66
70
|
readonly restoreInstance: RestoreFormInstance;
|
|
67
71
|
}
|
|
@@ -70,25 +74,9 @@ export interface LoadFormFailureResult extends BaseLoadFormResult {
|
|
|
70
74
|
readonly status: 'failure';
|
|
71
75
|
readonly warnings: LoadFormWarnings | null;
|
|
72
76
|
readonly error: LoadFormFailureError;
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* @example A temporary demo integration was built during development of this
|
|
76
|
-
* interface.
|
|
77
|
-
*
|
|
78
|
-
* @see
|
|
79
|
-
* {@link https://github.com/getodk/web-forms/pull/345/commits/9ef36355d89dd1450d3a87c3a55506bb9b0fc414}
|
|
80
|
-
*/
|
|
81
77
|
readonly createInstance: FailedLoadFormResultMethod<CreateFormInstance>;
|
|
82
|
-
|
|
78
|
+
readonly resetInstance: FailedLoadFormResultMethod<ResetFormInstance>;
|
|
83
79
|
readonly editInstance: FailedLoadFormResultMethod<EditFormInstance>;
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* @example A temporary demo integration was built during development of this
|
|
87
|
-
* interface.
|
|
88
|
-
*
|
|
89
|
-
* @see
|
|
90
|
-
* {@link https://github.com/getodk/web-forms/pull/345/commits/9ef36355d89dd1450d3a87c3a55506bb9b0fc414}
|
|
91
|
-
*/
|
|
92
80
|
readonly restoreInstance: FailedLoadFormResultMethod<RestoreFormInstance>;
|
|
93
81
|
}
|
|
94
82
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { RootNode } from '../RootNode.ts';
|
|
2
|
+
import type { CreatedFormInstance } from './CreateFormInstance.ts';
|
|
3
|
+
import type { FormInstanceConfig } from './FormInstanceConfig.ts';
|
|
4
|
+
import type { LoadForm } from './LoadForm.ts';
|
|
5
|
+
import type { LoadFormResult } from './LoadFormResult.ts';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @todo This is fallible! Client-facing interfaces will need to account for
|
|
9
|
+
* this. We've begun addressing fallibility _at the interface level_ in
|
|
10
|
+
* {@link LoadForm} (with {@link LoadFormResult}). We'll eventually have a more
|
|
11
|
+
* general interface pattern for this, and we'll apply it here as well. The baby
|
|
12
|
+
* step approach in {@link LoadFormResult} is impractical here due to
|
|
13
|
+
* engine-internal designs, and revising that is currently out of scope. As
|
|
14
|
+
* such, explicit interface-level documentation of fallibility is deferred here,
|
|
15
|
+
* on {@link RootNode} itself, and into any of its sub-interfaces.
|
|
16
|
+
*/
|
|
17
|
+
export type ResetFormInstance = (config?: FormInstanceConfig) => CreatedFormInstance;
|
|
@@ -42,6 +42,7 @@ export class FormInstance<Mode extends FormInstanceInitializationMode>
|
|
|
42
42
|
clientStateFactory: instanceConfig.stateFactory ?? identity,
|
|
43
43
|
computeAttachmentName: instanceConfig.instanceAttachments?.fileNameFactory ?? (() => null),
|
|
44
44
|
preloadProperties: instanceConfig.preloadProperties ?? {},
|
|
45
|
+
geolocationProvider: instanceConfig.geolocationProvider,
|
|
45
46
|
};
|
|
46
47
|
const primaryInstanceOptions: PrimaryInstanceOptions<Mode> = {
|
|
47
48
|
...options.instanceOptions,
|
|
@@ -49,6 +50,7 @@ export class FormInstance<Mode extends FormInstanceInitializationMode>
|
|
|
49
50
|
initialState,
|
|
50
51
|
config,
|
|
51
52
|
};
|
|
53
|
+
|
|
52
54
|
const { root } = new PrimaryInstance(primaryInstanceOptions);
|
|
53
55
|
|
|
54
56
|
this.mode = mode;
|
|
@@ -29,6 +29,7 @@ export abstract class BaseFormResult<Status extends FormResultStatus> {
|
|
|
29
29
|
readonly error: BaseFormResultProperty<Status, 'error'>;
|
|
30
30
|
|
|
31
31
|
abstract readonly createInstance: BaseFormResultProperty<Status, 'createInstance'>;
|
|
32
|
+
abstract readonly resetInstance: BaseFormResultProperty<Status, 'resetInstance'>;
|
|
32
33
|
abstract readonly editInstance: BaseFormResultProperty<Status, 'editInstance'>;
|
|
33
34
|
abstract readonly restoreInstance: BaseFormResultProperty<Status, 'restoreInstance'>;
|
|
34
35
|
|
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
} from '../../client/form/EditFormInstance.ts';
|
|
6
6
|
import type { FormInstanceConfig } from '../../client/form/FormInstanceConfig.ts';
|
|
7
7
|
import type { FormResultStatus } from '../../client/form/LoadFormResult.ts';
|
|
8
|
+
import type { ResetFormInstance } from '../../client/form/ResetFormInstance.ts';
|
|
8
9
|
import type {
|
|
9
10
|
RestoreFormInstance,
|
|
10
11
|
RestoreFormInstanceInput,
|
|
@@ -13,7 +14,8 @@ import { ErrorProductionDesignPendingError } from '../../error/ErrorProductionDe
|
|
|
13
14
|
import { InitialInstanceState } from '../../instance/input/InitialInstanceState.ts';
|
|
14
15
|
import type { BasePrimaryInstanceOptions } from '../../instance/PrimaryInstance.ts';
|
|
15
16
|
import type { FormResource } from '../../instance/resource.ts';
|
|
16
|
-
import type
|
|
17
|
+
import { type ReactiveScope } from '../../lib/reactivity/scope.ts';
|
|
18
|
+
import { createPotentiallyClientOwnedReactiveScope } from '../createPotentiallyClientOwnedReactiveScope.ts';
|
|
17
19
|
import type { InstantiableFormResult } from '../FormInstance.ts';
|
|
18
20
|
import { FormInstance } from '../FormInstance.ts';
|
|
19
21
|
import type { BaseFormResultProperty } from './BaseFormResult.ts';
|
|
@@ -37,6 +39,7 @@ export abstract class BaseInstantiableFormResult<
|
|
|
37
39
|
Status extends InstantiableFormResultStatus,
|
|
38
40
|
> extends BaseFormResult<Status> {
|
|
39
41
|
readonly createInstance: CreateFormInstance;
|
|
42
|
+
readonly resetInstance: ResetFormInstance;
|
|
40
43
|
readonly editInstance: EditFormInstance;
|
|
41
44
|
readonly restoreInstance: RestoreFormInstance;
|
|
42
45
|
|
|
@@ -60,6 +63,12 @@ export abstract class BaseInstantiableFormResult<
|
|
|
60
63
|
});
|
|
61
64
|
};
|
|
62
65
|
|
|
66
|
+
this.resetInstance = (instanceConfig: FormInstanceConfig = {}) => {
|
|
67
|
+
instanceOptions.scope.dispose();
|
|
68
|
+
instanceOptions.scope = createPotentiallyClientOwnedReactiveScope();
|
|
69
|
+
return this.createInstance(instanceConfig);
|
|
70
|
+
};
|
|
71
|
+
|
|
63
72
|
this.editInstance = async (
|
|
64
73
|
input: EditFormInstanceInput,
|
|
65
74
|
instanceConfig: FormInstanceConfig = {}
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
LoadFormFailureResult,
|
|
7
7
|
LoadFormWarnings,
|
|
8
8
|
} from '../../client/form/LoadFormResult.ts';
|
|
9
|
+
import type { ResetFormInstance } from '../../client/form/ResetFormInstance.ts';
|
|
9
10
|
import type { RestoreFormInstance } from '../../client/form/RestoreFormInstance.ts';
|
|
10
11
|
import { LoadFormFailureError } from '../../error/LoadFormFailureError.ts';
|
|
11
12
|
import { BaseFormResult } from './BaseFormResult.ts';
|
|
@@ -25,6 +26,7 @@ const failedFormResultMethodFactory = <T extends AnyFunction>(
|
|
|
25
26
|
|
|
26
27
|
export class FormFailureResult extends BaseFormResult<'failure'> implements LoadFormFailureResult {
|
|
27
28
|
readonly createInstance: FailedLoadFormResultMethod<CreateFormInstance>;
|
|
29
|
+
readonly resetInstance: FailedLoadFormResultMethod<ResetFormInstance>;
|
|
28
30
|
readonly editInstance: FailedLoadFormResultMethod<EditFormInstance>;
|
|
29
31
|
readonly restoreInstance: FailedLoadFormResultMethod<RestoreFormInstance>;
|
|
30
32
|
|
|
@@ -38,6 +40,7 @@ export class FormFailureResult extends BaseFormResult<'failure'> implements Load
|
|
|
38
40
|
});
|
|
39
41
|
|
|
40
42
|
this.createInstance = failedFormResultMethodFactory(error);
|
|
43
|
+
this.resetInstance = failedFormResultMethodFactory(error);
|
|
41
44
|
this.editInstance = failedFormResultMethodFactory(error);
|
|
42
45
|
this.restoreInstance = failedFormResultMethodFactory(error);
|
|
43
46
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { getOwner, type Owner } from 'solid-js';
|
|
2
|
+
import { createReactiveScope, type ReactiveScope } from '../lib/reactivity/scope';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Creates a {@link ReactiveScope | reactive scope} from which all form
|
|
6
|
+
* instances derive, and:
|
|
7
|
+
*
|
|
8
|
+
* - if a client loads a form within a Solid reactive context, the scope will be
|
|
9
|
+
* disposed along with the client's reactive context; OR
|
|
10
|
+
* - if a client loads a form outside a Solid reactive context (typically: if a
|
|
11
|
+
* client does not use Solid reactivity), the scope will disposed if and when
|
|
12
|
+
* the engine drops access to the loaded form
|
|
13
|
+
*
|
|
14
|
+
* **IMPORTANT:** this **MUST** be called synchronously. If it is called in an
|
|
15
|
+
* `async` function, it **MUST** be called before any `await` expression; if it
|
|
16
|
+
* is called in any other flow with mixed synchrony, it must be called before
|
|
17
|
+
* yielding to the event loop. Failing to do this will cause the engine to lose
|
|
18
|
+
* access to a client's Solid reactive context, potentially leaking form
|
|
19
|
+
* reactivity indefinitely.
|
|
20
|
+
*/
|
|
21
|
+
export const createPotentiallyClientOwnedReactiveScope = (): ReactiveScope => {
|
|
22
|
+
/**
|
|
23
|
+
* A {@link clientOwner | client owner} is the owner of a client's Solid
|
|
24
|
+
* reactive context, if one exists. If none exists, the {@link ReactiveScope}
|
|
25
|
+
* is fully owned by the engine.
|
|
26
|
+
*/
|
|
27
|
+
const clientOwner: Owner | null = getOwner();
|
|
28
|
+
|
|
29
|
+
return createReactiveScope({ owner: clientOwner });
|
|
30
|
+
};
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type { Owner } from 'solid-js';
|
|
2
|
-
import { getOwner } from 'solid-js';
|
|
3
1
|
import { MISSING_RESOURCE_BEHAVIOR } from '../client/constants.ts';
|
|
4
2
|
import type { FormResource } from '../client/form/FormResource.ts';
|
|
5
3
|
import type { LoadForm, LoadFormOptions } from '../client/form/LoadForm.ts';
|
|
@@ -7,40 +5,12 @@ import type { LoadFormResult } from '../client/form/LoadFormResult.ts';
|
|
|
7
5
|
import { LoadFormFailureError } from '../error/LoadFormFailureError.ts';
|
|
8
6
|
import { retrieveFormDefinition } from '../instance/resource.ts';
|
|
9
7
|
import type { ReactiveScope } from '../lib/reactivity/scope.ts';
|
|
10
|
-
import { createReactiveScope } from '../lib/reactivity/scope.ts';
|
|
11
8
|
import { XFormDOM } from '../parse/XFormDOM.ts';
|
|
12
9
|
import { XFormDefinition } from '../parse/XFormDefinition.ts';
|
|
13
10
|
import { SecondaryInstancesDefinition } from '../parse/model/SecondaryInstance/SecondaryInstancesDefinition.ts';
|
|
14
11
|
import { FormFailureResult } from './FormResult/FormFailureResult.ts';
|
|
15
12
|
import { FormSuccessResult } from './FormResult/FormSuccessResult.ts';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Creates a {@link ReactiveScope | reactive scope} from which all form
|
|
19
|
-
* instances derive, and:
|
|
20
|
-
*
|
|
21
|
-
* - if a client loads a form within a Solid reactive context, the scope will be
|
|
22
|
-
* disposed along with the client's reactive context; OR
|
|
23
|
-
* - if a client loads a form outside a Solid reactive context (typically: if a
|
|
24
|
-
* client does not use Solid reactivity), the scope will disposed if and when
|
|
25
|
-
* the engine drops access to the loaded form
|
|
26
|
-
*
|
|
27
|
-
* **IMPORTANT:** this **MUST** be called synchronously. If it is called in an
|
|
28
|
-
* `async` function, it **MUST** be called before any `await` expression; if it
|
|
29
|
-
* is called in any other flow with mixed synchrony, it must be called before
|
|
30
|
-
* yielding to the event loop. Failing to do this will cause the engine to lose
|
|
31
|
-
* access to a client's Solid reactive context, potentially leaking form
|
|
32
|
-
* reactivity indefinitely.
|
|
33
|
-
*/
|
|
34
|
-
const createPotentiallyClientOwnedReactiveScope = (): ReactiveScope => {
|
|
35
|
-
/**
|
|
36
|
-
* A {@link clientOwner | client owner} is the owner of a client's Solid
|
|
37
|
-
* reactive context, if one exists. If none exists, the {@link ReactiveScope}
|
|
38
|
-
* is fully owned by the engine.
|
|
39
|
-
*/
|
|
40
|
-
const clientOwner: Owner | null = getOwner();
|
|
41
|
-
|
|
42
|
-
return createReactiveScope({ owner: clientOwner });
|
|
43
|
-
};
|
|
13
|
+
import { createPotentiallyClientOwnedReactiveScope } from './createPotentiallyClientOwnedReactiveScope.ts';
|
|
44
14
|
|
|
45
15
|
type GlobalFetch = typeof globalThis.fetch;
|
|
46
16
|
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { XPathNodeKindKey } from '@getodk/xpath';
|
|
2
2
|
import type { Accessor } from 'solid-js';
|
|
3
3
|
import type { AttributeNode } from '../client/AttributeNode.ts';
|
|
4
|
-
import type {
|
|
4
|
+
import type { InstanceState, NullValidationState } from '../client/index.ts';
|
|
5
5
|
import type { XFormsXPathAttribute } from '../integration/xpath/adapter/XFormsXPathNode.ts';
|
|
6
|
-
import type { EngineXPathEvaluator } from '../integration/xpath/EngineXPathEvaluator.ts';
|
|
7
6
|
import type { StaticAttribute } from '../integration/xpath/static-dom/StaticAttribute.ts';
|
|
8
7
|
import { createAttributeNodeInstanceState } from '../lib/client-reactivity/instance-state/createAttributeNodeInstanceState.ts';
|
|
9
8
|
import {
|
|
@@ -12,6 +11,10 @@ import {
|
|
|
12
11
|
type RuntimeValue,
|
|
13
12
|
} from '../lib/codecs/getSharedValueCodec.ts';
|
|
14
13
|
import type { RuntimeValueSetter, RuntimeValueState } from '../lib/codecs/ValueCodec.ts';
|
|
14
|
+
import {
|
|
15
|
+
createAttributeState,
|
|
16
|
+
type AttributeState,
|
|
17
|
+
} from '../lib/reactivity/createAttributeState.ts';
|
|
15
18
|
import { createInstanceValueState } from '../lib/reactivity/createInstanceValueState.ts';
|
|
16
19
|
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
17
20
|
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
@@ -19,31 +22,32 @@ import {
|
|
|
19
22
|
createSharedNodeState,
|
|
20
23
|
type SharedNodeState,
|
|
21
24
|
} from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
22
|
-
import type { ReactiveScope } from '../lib/reactivity/scope.ts';
|
|
23
25
|
import type { SimpleAtomicState } from '../lib/reactivity/types.ts';
|
|
24
26
|
import type { AttributeDefinition } from '../parse/model/AttributeDefinition.ts';
|
|
25
|
-
import
|
|
27
|
+
import { DescendantNode, type DescendantNodeStateSpec } from './abstract/DescendantNode.ts';
|
|
28
|
+
import type { AnyNode } from './hierarchy.ts';
|
|
26
29
|
import type { AttributeContext } from './internal-api/AttributeContext.ts';
|
|
27
|
-
import type { InstanceConfig } from './internal-api/InstanceConfig.ts';
|
|
28
30
|
import type { DecodeInstanceValue } from './internal-api/InstanceValueContext.ts';
|
|
29
31
|
import type { ClientReactiveSerializableAttributeNode } from './internal-api/serialization/ClientReactiveSerializableAttributeNode.ts';
|
|
30
|
-
import type { PrimaryInstance } from './PrimaryInstance.ts';
|
|
31
32
|
import type { Root } from './Root.ts';
|
|
32
33
|
|
|
33
|
-
export interface AttributeStateSpec {
|
|
34
|
+
export interface AttributeStateSpec extends DescendantNodeStateSpec<string> {
|
|
35
|
+
readonly children: null;
|
|
36
|
+
readonly attributes: Accessor<Attribute[]>;
|
|
34
37
|
readonly value: SimpleAtomicState<string>;
|
|
35
38
|
readonly instanceValue: Accessor<string>;
|
|
36
39
|
readonly relevant: Accessor<boolean>;
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
export class Attribute
|
|
43
|
+
extends DescendantNode<AttributeDefinition, AttributeStateSpec, AnyNode, null>
|
|
40
44
|
implements
|
|
41
45
|
AttributeNode,
|
|
42
46
|
ClientReactiveSerializableAttributeNode,
|
|
43
47
|
AttributeContext,
|
|
44
48
|
XFormsXPathAttribute
|
|
45
49
|
{
|
|
46
|
-
readonly [XPathNodeKindKey] = 'attribute';
|
|
50
|
+
override readonly [XPathNodeKindKey] = 'attribute';
|
|
47
51
|
|
|
48
52
|
protected readonly state: SharedNodeState<AttributeStateSpec>;
|
|
49
53
|
protected readonly engineState: EngineState<AttributeStateSpec>;
|
|
@@ -62,60 +66,30 @@ export class Attribute
|
|
|
62
66
|
protected readonly getInstanceValue: Accessor<string>;
|
|
63
67
|
protected readonly valueState: RuntimeValueState<RuntimeValue<'string'>>;
|
|
64
68
|
protected readonly setValueState: RuntimeValueSetter<RuntimeInputValue<'string'>>;
|
|
65
|
-
readonly
|
|
66
|
-
readonly getActiveLanguage: Accessor<ActiveLanguage>;
|
|
67
|
-
readonly contextNode: AnyNode;
|
|
68
|
-
readonly scope: ReactiveScope;
|
|
69
|
-
readonly rootDocument: PrimaryInstance;
|
|
70
|
-
readonly instanceConfig: InstanceConfig;
|
|
71
|
-
|
|
72
|
-
readonly root: Root;
|
|
69
|
+
readonly attributeState: AttributeState;
|
|
73
70
|
|
|
74
|
-
readonly
|
|
75
|
-
return this.owner.isRelevant();
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
readonly isAttached: Accessor<boolean> = () => {
|
|
71
|
+
override readonly isAttached: Accessor<boolean> = () => {
|
|
79
72
|
return this.owner.isAttached();
|
|
80
73
|
};
|
|
81
74
|
|
|
82
|
-
readonly
|
|
83
|
-
return true;
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
readonly hasReadonlyAncestor: Accessor<boolean> = () => {
|
|
87
|
-
const { owner } = this;
|
|
88
|
-
return owner.hasReadonlyAncestor() || owner.isReadonly();
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
readonly hasNonRelevantAncestor: Accessor<boolean> = () => {
|
|
92
|
-
const { owner } = this;
|
|
93
|
-
return owner.hasNonRelevantAncestor() || !owner.isRelevant();
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
readonly contextReference = (): string => {
|
|
97
|
-
return this.owner.contextReference() + '/@' + this.definition.qualifiedName.getPrefixedName();
|
|
98
|
-
};
|
|
75
|
+
override readonly getXPathValue: () => string;
|
|
99
76
|
|
|
100
77
|
constructor(
|
|
101
78
|
readonly owner: AnyNode,
|
|
102
|
-
|
|
103
|
-
readonly instanceNode: StaticAttribute
|
|
79
|
+
definition: AttributeDefinition,
|
|
80
|
+
override readonly instanceNode: StaticAttribute
|
|
104
81
|
) {
|
|
105
|
-
const
|
|
82
|
+
const computeReference = () => {
|
|
83
|
+
return `${this.owner.contextReference()}/@${this.definition.qualifiedName.getPrefixedName()}`;
|
|
84
|
+
};
|
|
106
85
|
|
|
107
|
-
|
|
108
|
-
this.scope = owner.scope;
|
|
109
|
-
this.rootDocument = owner.rootDocument;
|
|
86
|
+
super(owner, instanceNode, definition, { computeReference });
|
|
110
87
|
|
|
111
|
-
|
|
112
|
-
this.instanceConfig = owner.instanceConfig;
|
|
88
|
+
const codec = getSharedValueCodec('string');
|
|
113
89
|
|
|
114
|
-
this.getActiveLanguage = owner.getActiveLanguage;
|
|
115
90
|
this.validationState = { violations: [] };
|
|
116
91
|
|
|
117
92
|
this.valueType = 'string';
|
|
118
|
-
this.evaluator = owner.evaluator;
|
|
119
93
|
this.decodeInstanceValue = codec.decodeInstanceValue;
|
|
120
94
|
|
|
121
95
|
const instanceValueState = createInstanceValueState(this);
|
|
@@ -134,6 +108,15 @@ export class Attribute
|
|
|
134
108
|
value: this.valueState,
|
|
135
109
|
instanceValue: this.getInstanceValue,
|
|
136
110
|
relevant: this.owner.isRelevant,
|
|
111
|
+
|
|
112
|
+
readonly: () => true,
|
|
113
|
+
reference: this.contextReference,
|
|
114
|
+
required: () => false,
|
|
115
|
+
children: null,
|
|
116
|
+
label: () => null,
|
|
117
|
+
hint: () => null,
|
|
118
|
+
attributes: () => [],
|
|
119
|
+
valueOptions: () => [],
|
|
137
120
|
},
|
|
138
121
|
this.instanceConfig
|
|
139
122
|
);
|
|
@@ -142,6 +125,11 @@ export class Attribute
|
|
|
142
125
|
this.engineState = state.engineState;
|
|
143
126
|
this.currentState = state.currentState;
|
|
144
127
|
this.instanceState = createAttributeNodeInstanceState(this);
|
|
128
|
+
this.attributeState = createAttributeState(this.scope);
|
|
129
|
+
|
|
130
|
+
this.getXPathValue = () => {
|
|
131
|
+
return this.getInstanceValue();
|
|
132
|
+
};
|
|
145
133
|
}
|
|
146
134
|
|
|
147
135
|
setValue(value: string): Root {
|
|
@@ -150,15 +138,11 @@ export class Attribute
|
|
|
150
138
|
return this.root;
|
|
151
139
|
}
|
|
152
140
|
|
|
153
|
-
|
|
141
|
+
override getAttributes(): readonly Attribute[] {
|
|
154
142
|
return [];
|
|
155
143
|
}
|
|
156
144
|
|
|
157
|
-
|
|
145
|
+
getChildren(): readonly [] {
|
|
158
146
|
return [];
|
|
159
147
|
}
|
|
160
|
-
|
|
161
|
-
getXPathValue(): string {
|
|
162
|
-
return '';
|
|
163
|
-
}
|
|
164
148
|
}
|
package/src/instance/Group.ts
CHANGED
|
@@ -8,7 +8,10 @@ import type { AncestorNodeValidationState } from '../client/validation.ts';
|
|
|
8
8
|
import type { XFormsXPathElement } from '../integration/xpath/adapter/XFormsXPathNode.ts';
|
|
9
9
|
import type { StaticElement } from '../integration/xpath/static-dom/StaticElement.ts';
|
|
10
10
|
import { createParentNodeInstanceState } from '../lib/client-reactivity/instance-state/createParentNodeInstanceState.ts';
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
createAttributeState,
|
|
13
|
+
type AttributeState,
|
|
14
|
+
} from '../lib/reactivity/createAttributeState.ts';
|
|
12
15
|
import type { ChildrenState } from '../lib/reactivity/createChildrenState.ts';
|
|
13
16
|
import { createChildrenState } from '../lib/reactivity/createChildrenState.ts';
|
|
14
17
|
import type { MaterializedChildren } from '../lib/reactivity/materializeCurrentStateChildren.ts';
|
|
@@ -53,6 +56,7 @@ export class Group
|
|
|
53
56
|
// InstanceNode
|
|
54
57
|
protected readonly state: SharedNodeState<GroupStateSpec>;
|
|
55
58
|
protected override engineState: EngineState<GroupStateSpec>;
|
|
59
|
+
readonly attributeState: AttributeState;
|
|
56
60
|
|
|
57
61
|
// GroupNode
|
|
58
62
|
readonly nodeType = 'group';
|
|
@@ -72,7 +76,7 @@ export class Group
|
|
|
72
76
|
this.appearances = definition.bodyElement?.appearances ?? null;
|
|
73
77
|
|
|
74
78
|
const childrenState = createChildrenState<Group, GeneralChildNode>(this);
|
|
75
|
-
|
|
79
|
+
this.attributeState = createAttributeState(this.scope);
|
|
76
80
|
|
|
77
81
|
this.childrenState = childrenState;
|
|
78
82
|
|
|
@@ -87,7 +91,7 @@ export class Group
|
|
|
87
91
|
label: createNodeLabel(this, definition),
|
|
88
92
|
hint: null,
|
|
89
93
|
children: childrenState.childIds,
|
|
90
|
-
attributes: attributeState.getAttributes,
|
|
94
|
+
attributes: this.attributeState.getAttributes,
|
|
91
95
|
valueOptions: null,
|
|
92
96
|
value: null,
|
|
93
97
|
},
|
|
@@ -103,7 +107,7 @@ export class Group
|
|
|
103
107
|
);
|
|
104
108
|
|
|
105
109
|
childrenState.setChildren(buildChildren(this));
|
|
106
|
-
attributeState.setAttributes(buildAttributes(this));
|
|
110
|
+
this.attributeState.setAttributes(buildAttributes(this));
|
|
107
111
|
this.validationState = createAggregatedViolations(this, this.instanceConfig);
|
|
108
112
|
this.instanceState = createParentNodeInstanceState(this);
|
|
109
113
|
}
|
|
@@ -111,4 +115,8 @@ export class Group
|
|
|
111
115
|
getChildren(): readonly GeneralChildNode[] {
|
|
112
116
|
return this.childrenState.getChildren();
|
|
113
117
|
}
|
|
118
|
+
|
|
119
|
+
override getAttributes(): readonly Attribute[] {
|
|
120
|
+
return this.attributeState.getAttributes();
|
|
121
|
+
}
|
|
114
122
|
}
|