node-opcua-address-space 2.83.0 → 2.85.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.
Files changed (41) hide show
  1. package/dist/source/continuation_points/continuation_point_manager.js +6 -1
  2. package/dist/source/continuation_points/continuation_point_manager.js.map +1 -1
  3. package/dist/source/loader/ensure_datatype_extracted.js +1 -1
  4. package/dist/source/loader/ensure_datatype_extracted.js.map +1 -1
  5. package/dist/source/loader/load_nodeset2.js +1 -1
  6. package/dist/source/loader/load_nodeset2.js.map +1 -1
  7. package/dist/source/pseudo_session.d.ts +15 -1
  8. package/dist/source/pseudo_session.js +86 -37
  9. package/dist/source/pseudo_session.js.map +1 -1
  10. package/dist/src/address_space.d.ts +0 -4
  11. package/dist/src/address_space.js +4 -13
  12. package/dist/src/address_space.js.map +1 -1
  13. package/dist/src/base_node_impl.js +1 -1
  14. package/dist/src/base_node_impl.js.map +1 -1
  15. package/dist/src/base_node_private.js +13 -7
  16. package/dist/src/base_node_private.js.map +1 -1
  17. package/dist/src/namespace_impl.js +1 -0
  18. package/dist/src/namespace_impl.js.map +1 -1
  19. package/dist/src/nodeset_tools/construct_namespace_dependency.js +7 -0
  20. package/dist/src/nodeset_tools/construct_namespace_dependency.js.map +1 -1
  21. package/dist/src/nodeset_tools/nodeset_to_xml.js +33 -36
  22. package/dist/src/nodeset_tools/nodeset_to_xml.js.map +1 -1
  23. package/dist/src/tool_isSupertypeOf.d.ts +1 -0
  24. package/dist/src/tool_isSupertypeOf.js +7 -1
  25. package/dist/src/tool_isSupertypeOf.js.map +1 -1
  26. package/dist/src/ua_reference_type_impl.d.ts +1 -1
  27. package/dist/src/ua_variable_impl.js +1 -1
  28. package/dist/src/ua_variable_impl.js.map +1 -1
  29. package/package.json +35 -35
  30. package/source/continuation_points/continuation_point_manager.ts +6 -2
  31. package/source/loader/ensure_datatype_extracted.ts +1 -1
  32. package/source/loader/load_nodeset2.ts +1 -1
  33. package/source/pseudo_session.ts +120 -46
  34. package/src/address_space.ts +4 -16
  35. package/src/base_node_impl.ts +8 -3
  36. package/src/base_node_private.ts +23 -17
  37. package/src/namespace_impl.ts +6 -3
  38. package/src/nodeset_tools/construct_namespace_dependency.ts +9 -0
  39. package/src/nodeset_tools/nodeset_to_xml.ts +45 -44
  40. package/src/tool_isSupertypeOf.ts +5 -0
  41. package/src/ua_variable_impl.ts +1 -1
@@ -32,6 +32,96 @@ import { callMethodHelper } from "./helpers/call_helpers";
32
32
  import { SessionContext } from "./session_context";
33
33
 
34
34
  const errorLog = make_errorLog("PseudoSession");
35
+
36
+ function coerceBrowseDescription(browseDescription: BrowseDescriptionLike): BrowseDescription {
37
+ if (typeof browseDescription === "string") {
38
+ return coerceBrowseDescription({
39
+ nodeId: resolveNodeId(browseDescription)
40
+ });
41
+ } else if (browseDescription instanceof BrowseDescription) {
42
+ return browseDescription;
43
+ } else {
44
+ return new BrowseDescription(browseDescription);
45
+ }
46
+ }
47
+ export interface InnerBrowseEngine {
48
+ requestedMaxReferencesPerNode: number;
49
+ maxBrowseContinuationPoints: number;
50
+ continuationPointManager: ContinuationPointManager;
51
+ context: ISessionContext;
52
+ browseAll: (nodesToBrowse: BrowseDescriptionOptions[], callack: ResponseCallback<BrowseResult[]>) => void;
53
+ }
54
+
55
+ export function innerBrowse(
56
+ engine: InnerBrowseEngine,
57
+ nodesToBrowse: BrowseDescriptionOptions[],
58
+ callback?: ResponseCallback<BrowseResult[]>
59
+ ): void {
60
+ engine.browseAll(nodesToBrowse, (err, results) => {
61
+ if (err || !results) {
62
+ return callback!(err);
63
+ }
64
+ // handle continuation points
65
+ results = results.map((result: BrowseResult, index) => {
66
+ assert(!result.continuationPoint);
67
+ // istanbul ignore next
68
+ if (!engine.continuationPointManager) {
69
+ return new BrowseResult({ statusCode: StatusCodes.BadNoContinuationPoints });
70
+ }
71
+ if (index === 0) {
72
+ // clear previous continuation points
73
+ engine.continuationPointManager.clearContinuationPoints();
74
+ }
75
+ if (engine.continuationPointManager.hasReachedMaximum(engine.maxBrowseContinuationPoints)) {
76
+ return new BrowseResult({ statusCode: StatusCodes.BadNoContinuationPoints });
77
+ }
78
+
79
+ const truncatedResult = engine.continuationPointManager.registerReferences(
80
+ engine.requestedMaxReferencesPerNode,
81
+ result.references || [],
82
+ { continuationPoint: null, index }
83
+ );
84
+ let { statusCode } = truncatedResult;
85
+ const { continuationPoint, values } = truncatedResult;
86
+ assert(statusCode === StatusCodes.Good || statusCode === StatusCodes.GoodNoData);
87
+ statusCode = result.statusCode;
88
+ return new BrowseResult({
89
+ statusCode,
90
+ continuationPoint,
91
+ references: values
92
+ });
93
+ });
94
+ callback!(null, results);
95
+ });
96
+ }
97
+
98
+ export interface InnerBrowseNextEngine {
99
+ continuationPointManager: ContinuationPointManager;
100
+ }
101
+ export function innerBrowseNext(
102
+ engine: InnerBrowseNextEngine,
103
+ continuationPoints: Buffer[],
104
+ releaseContinuationPoints: boolean,
105
+ callback?: ResponseCallback<BrowseResult[]>
106
+ ): void {
107
+ const results = continuationPoints
108
+ .map((continuationPoint: ContinuationPoint, index: number) => {
109
+ return engine.continuationPointManager.getNextReferences(0, {
110
+ continuationPoint,
111
+ index,
112
+ releaseContinuationPoints
113
+ });
114
+ })
115
+ .map(
116
+ (r) =>
117
+ new BrowseResult({
118
+ statusCode: r.statusCode,
119
+ continuationPoint: r.continuationPoint,
120
+ references: r.values
121
+ })
122
+ );
123
+ callback!(null, results);
124
+ }
35
125
  /**
36
126
  * Pseudo session is an helper object that exposes the same async methods
37
127
  * than the ClientSession. It can be used on a server address space.
@@ -44,6 +134,7 @@ const errorLog = make_errorLog("PseudoSession");
44
134
  */
45
135
  export class PseudoSession implements IBasicSession {
46
136
  public requestedMaxReferencesPerNode = 0;
137
+ public maxBrowseContinuationPoints = 0; // 0=no limits
47
138
  private _sessionId: NodeId = new NodeId(NodeIdType.GUID, randomGuid());
48
139
  private readonly addressSpace: IAddressSpace;
49
140
  private readonly continuationPointManager: ContinuationPointManager;
@@ -63,40 +154,36 @@ export class PseudoSession implements IBasicSession {
63
154
  public browse(nodeToBrowse: BrowseDescriptionLike): Promise<BrowseResult>;
64
155
  public browse(nodesToBrowse: BrowseDescriptionLike[]): Promise<BrowseResult[]>;
65
156
  public browse(nodesToBrowse: BrowseDescriptionLike | BrowseDescriptionLike[], callback?: ResponseCallback<any>): any {
66
- setImmediate(() => {
67
- const isArray = Array.isArray(nodesToBrowse);
68
- if (!isArray) {
69
- nodesToBrowse = [nodesToBrowse as BrowseDescriptionLike];
70
- }
71
- let results: BrowseResult[] = [];
157
+ const isArray = Array.isArray(nodesToBrowse);
158
+ if (!isArray) {
159
+ return this.browse([nodesToBrowse as BrowseDescriptionLike], (err, results) => {
160
+ return callback!(err, results ? results[0] : undefined);
161
+ });
162
+ }
163
+ const browseAll = (nodesToBrowse: BrowseDescriptionOptions[], callack: ResponseCallback<BrowseResult[]>) => {
164
+ const results: BrowseResult[] = [];
72
165
  for (const browseDescription of nodesToBrowse as BrowseDescriptionOptions[]) {
73
166
  browseDescription.referenceTypeId = resolveNodeId(browseDescription.referenceTypeId!);
74
- const _browseDescription =
75
- browseDescription instanceof BrowseDescription ? browseDescription : new BrowseDescription(browseDescription);
167
+ const _browseDescription = coerceBrowseDescription(browseDescription);
76
168
  const nodeId = resolveNodeId(_browseDescription.nodeId);
77
169
  const r = this.addressSpace.browseSingleNode(nodeId, _browseDescription, this.context);
78
170
  results.push(r);
79
171
  }
172
+ callack(null, results);
173
+ };
80
174
 
81
- // handle continuation points
82
- results = results.map((result: BrowseResult, index) => {
83
- assert(!result.continuationPoint);
84
- const r = this.continuationPointManager.registerReferences(
85
- this.requestedMaxReferencesPerNode,
86
- result.references || [],
87
- { continuationPoint: null, index }
88
- );
89
- let { statusCode } = r;
90
- const { continuationPoint, values } = r;
91
- assert(statusCode === StatusCodes.Good || statusCode === StatusCodes.GoodNoData);
92
- statusCode = result.statusCode;
93
- return new BrowseResult({
94
- statusCode,
95
- continuationPoint,
96
- references: values
97
- });
98
- });
99
- callback!(null, isArray ? results : results[0]);
175
+ setImmediate(() => {
176
+ innerBrowse(
177
+ {
178
+ browseAll,
179
+ context: this.context,
180
+ continuationPointManager: this.continuationPointManager,
181
+ requestedMaxReferencesPerNode: this.requestedMaxReferencesPerNode,
182
+ maxBrowseContinuationPoints: this.maxBrowseContinuationPoints
183
+ },
184
+ nodesToBrowse as BrowseDescriptionOptions[],
185
+ callback
186
+ );
100
187
  });
101
188
  }
102
189
 
@@ -175,25 +262,12 @@ export class PseudoSession implements IBasicSession {
175
262
  callback!(null, _results![0]);
176
263
  });
177
264
  }
178
-
179
- const results = continuationPoints
180
- .map((continuationPoint: ContinuationPoint, index: number) => {
181
- return this.continuationPointManager.getNextReferences(0, {
182
- continuationPoint,
183
- index,
184
- releaseContinuationPoints
185
- });
186
- })
187
- .map(
188
- (r) =>
189
- new BrowseResult({
190
- statusCode: r.statusCode,
191
- continuationPoint: r.continuationPoint,
192
- references: r.values
193
- })
194
- );
195
-
196
- callback!(null, results);
265
+ innerBrowseNext(
266
+ { continuationPointManager: this.continuationPointManager },
267
+ continuationPoints,
268
+ releaseContinuationPoints,
269
+ callback
270
+ );
197
271
  });
198
272
  }
199
273
 
@@ -123,7 +123,6 @@ function isNodeIdString(str: unknown): boolean {
123
123
  return str.substring(0, 2) === "i=" || str.substring(0, 3) === "ns=";
124
124
  }
125
125
 
126
-
127
126
  /**
128
127
  * `AddressSpace` is a collection of UA nodes.
129
128
  *
@@ -423,7 +422,9 @@ export class AddressSpace implements AddressSpacePrivate {
423
422
  // +-> Structure
424
423
  // +-> Node
425
424
  // +-> ObjectNode
426
- if (dataType instanceof NodeId) {
425
+ if (dataType instanceof UADataTypeImpl) {
426
+ return this.findDataType(dataType.nodeId);
427
+ } else if (dataType instanceof NodeId) {
427
428
  return _find_by_node_id<UADataType>(this, dataType!, namespaceIndex);
428
429
  }
429
430
  if (typeof dataType === "number") {
@@ -1346,29 +1347,16 @@ export class AddressSpace implements AddressSpacePrivate {
1346
1347
  _nodeId = (_nodeId as any).nodeId as NodeId;
1347
1348
  }
1348
1349
  _nodeId = resolveNodeId(_nodeId);
1349
- /* istanbul ignore next */
1350
- if (!(_nodeId instanceof NodeId) || _nodeId.isEmpty()) {
1351
- // tslint:disable:no-console
1352
- console.log("xx =>", JSON.stringify(params, null, " "));
1353
- throw new Error(" Invalid reference nodeId " + _nodeId.toString());
1354
- }
1355
1350
  params.nodeId = _nodeId;
1356
1351
  }
1357
1352
  return new ReferenceImpl(params);
1358
1353
  }
1359
1354
 
1360
- /**
1361
- *
1362
- * @param references
1363
- */
1364
1355
  public normalizeReferenceTypes(references: AddReferenceOpts[] | ReferenceImpl[] | null): UAReference[] {
1365
1356
  if (!references || references.length === 0) {
1366
1357
  return [];
1367
1358
  }
1368
- references = references as UAReference[] | AddReferenceOpts[];
1369
- assert(Array.isArray(references));
1370
-
1371
- return (references as any).map((el: UAReference | AddReferenceOpts) => this.normalizeReferenceType(el));
1359
+ return references.map((el) => this.normalizeReferenceType(el));
1372
1360
  }
1373
1361
 
1374
1362
  // -- Historical Node -----------------------------------------------------------------------------------------
@@ -237,7 +237,13 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
237
237
  _cache.typeDefinitionObj = nodeId ? (this.addressSpace.findNode(nodeId) as UAObjectType | UAVariableType) : null;
238
238
  }
239
239
  if (!_cache.typeDefinitionObj) {
240
- warningLog("cannot find typeDefinitionObj ", this.browseName.toString(), this.nodeId.toString());
240
+ warningLog(
241
+ this.nodeClass,
242
+ "cannot find typeDefinitionObj ",
243
+ this.browseName.toString(),
244
+ this.nodeId.toString(),
245
+ NodeClass[this.nodeClass]
246
+ );
241
247
  }
242
248
  return _cache.typeDefinitionObj as UAObjectType | UAVariableType;
243
249
  }
@@ -390,7 +396,6 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
390
396
  return results;
391
397
  }
392
398
 
393
-
394
399
  public findReferences_no_cache(referenceTypeNode: UAReferenceType, isForward = true): UAReference[] {
395
400
  const _private = BaseNode_getPrivate(this);
396
401
  const result: UAReference[] = [];
@@ -500,7 +505,7 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
500
505
  // _cache._notifiers = this.findReferencesAsObject("HasNotifier", true);
501
506
  // }
502
507
  // return _cache._notifiers;
503
- return this.findReferencesAsObject("HasNotifier", true);
508
+ return this.findReferencesAsObject("HasNotifier", true);
504
509
  }
505
510
 
506
511
  /**
@@ -40,6 +40,7 @@ import { UANamespace_process_modelling_rule } from "./namespace_private";
40
40
  import { ReferenceImpl } from "./reference_impl";
41
41
  import { BaseNodeImpl, getReferenceType } from "./base_node_impl";
42
42
  import { AddressSpacePrivate } from "./address_space_private";
43
+ import { wipeMemorizedStuff } from "./tool_isSupertypeOf";
43
44
 
44
45
  // eslint-disable-next-line prefer-const
45
46
  let doTrace = checkDebugFlag("INSTANTIATE");
@@ -126,6 +127,7 @@ export function BaseNode_clearCache(node: BaseNode): void {
126
127
  if (_private && _private._cache) {
127
128
  _private._cache = {};
128
129
  }
130
+ wipeMemorizedStuff(node);
129
131
  }
130
132
  const hasTypeDefinition_ReferenceTypeNodeId = resolveNodeId("HasTypeDefinition");
131
133
 
@@ -681,6 +683,10 @@ function _cloneInterface(
681
683
 
682
684
  extraInfo = extraInfo || defaultExtraInfo;
683
685
  const addressSpace = node.addressSpace;
686
+
687
+ if (node.nodeClass !== NodeClass.Object && node.nodeClass !== NodeClass.Variable) {
688
+ return;
689
+ }
684
690
  const typeDefinitionNode = node.typeDefinitionObj;
685
691
  if (!typeDefinitionNode) {
686
692
  return;
@@ -813,25 +819,25 @@ export function _clone<T extends UAObject | UAVariable | UAMethod>(
813
819
  const browseNameMap = new Set<string>();
814
820
  _clone_children_references(this, cloneObj, options.copyAlsoModellingRules, newFilter!, extraInfo, browseNameMap);
815
821
 
816
- //
817
- let typeDefinitionNode: UAVariableType | UAObjectType | null = this.typeDefinitionObj;
818
- while (typeDefinitionNode) {
819
- doTrace &&
820
- traceLog(
821
- extraInfo?.pad(),
822
- chalk.blueBright("---------------------- Exploring ", typeDefinitionNode.browseName.toString())
822
+ if (this.nodeClass === NodeClass.Object || this.nodeClass === NodeClass.Variable) {
823
+ let typeDefinitionNode: UAVariableType | UAObjectType | null = this.typeDefinitionObj;
824
+ while (typeDefinitionNode) {
825
+ doTrace &&
826
+ traceLog(
827
+ extraInfo?.pad(),
828
+ chalk.blueBright("---------------------- Exploring ", typeDefinitionNode.browseName.toString())
829
+ );
830
+ _clone_children_references(
831
+ typeDefinitionNode,
832
+ cloneObj,
833
+ options.copyAlsoModellingRules,
834
+ newFilter,
835
+ extraInfo,
836
+ browseNameMap
823
837
  );
824
- _clone_children_references(
825
- typeDefinitionNode,
826
- cloneObj,
827
- options.copyAlsoModellingRules,
828
- newFilter,
829
- extraInfo,
830
- browseNameMap
831
- );
832
- typeDefinitionNode = typeDefinitionNode.subtypeOfObj;
838
+ typeDefinitionNode = typeDefinitionNode.subtypeOfObj;
839
+ }
833
840
  }
834
-
835
841
  _clone_non_hierarchical_references(this, cloneObj, options.copyAlsoModellingRules, newFilter, extraInfo, browseNameMap);
836
842
  }
837
843
  cloneObj.propagate_back_references();
@@ -10,7 +10,7 @@ import { AxisScaleEnumeration } from "node-opcua-data-access";
10
10
  import { AccessRestrictionsFlag, coerceLocalizedText, QualifiedNameLike } from "node-opcua-data-model";
11
11
  import { QualifiedName } from "node-opcua-data-model";
12
12
  import { BrowseDirection } from "node-opcua-data-model";
13
- import { LocalizedText, NodeClass } from "node-opcua-data-model";
13
+ import { NodeClass } from "node-opcua-data-model";
14
14
  import { dumpIf, make_errorLog } from "node-opcua-debug";
15
15
  import { NodeIdLike, NodeIdType, resolveNodeId } from "node-opcua-nodeid";
16
16
  import { NodeId } from "node-opcua-nodeid";
@@ -124,7 +124,7 @@ import { UAReferenceTypeImpl } from "./ua_reference_type_impl";
124
124
  import { UAViewImpl } from "./ua_view_impl";
125
125
  import { UAStateMachineImpl, UATransitionImpl } from "./state_machine/finite_state_machine";
126
126
  import { _addMultiStateValueDiscrete } from "./data_access/ua_multistate_value_discrete_impl";
127
- import { notDeepEqual } from "assert";
127
+
128
128
 
129
129
  function _makeHashKey(nodeId: NodeId): string | number {
130
130
  switch (nodeId.identifierType) {
@@ -615,7 +615,7 @@ export class NamespaceImpl implements NamespacePrivate {
615
615
  assert(!Object.prototype.hasOwnProperty.call(options, "nodeClass"));
616
616
  assert(Object.prototype.hasOwnProperty.call(options, "browseName"), "must provide a browseName");
617
617
 
618
- const options1 = options as any;
618
+ const options1 = options as unknown as { nodeClass: NodeClass; references: AddReferenceOpts[]; subtypeOf: UADataType };
619
619
  options1.nodeClass = NodeClass.DataType;
620
620
  options1.references = options.references || [];
621
621
 
@@ -638,6 +638,9 @@ export class NamespaceImpl implements NamespacePrivate {
638
638
  });
639
639
  }
640
640
  const node = this.internalCreateNode(options) as UADataType;
641
+
642
+ node.propagate_back_references();
643
+
641
644
  return node;
642
645
  }
643
646
 
@@ -1,9 +1,12 @@
1
1
  import { INamespace, UADataType, UAVariable, UAVariableType } from "node-opcua-address-space-base";
2
2
  import { NodeClass } from "node-opcua-data-model";
3
3
  import { StructureField } from "node-opcua-types";
4
+ import { make_warningLog } from "node-opcua-debug";
4
5
  import { NamespacePrivate } from "../namespace_private";
5
6
  import { BaseNodeImpl, getReferenceType } from "../base_node_impl";
6
7
 
8
+ const warningLog = make_warningLog(__filename);
9
+
7
10
  function _constructNamespaceDependency(
8
11
  namespace: INamespace,
9
12
  dependency: INamespace[],
@@ -43,6 +46,12 @@ function _constructNamespaceDependency(
43
46
  if (_visitedDataType.has(dataType.toString())) {
44
47
  return;
45
48
  }
49
+ // istanbul ignore next
50
+ if (dataTypeNode.nodeClass !== NodeClass.DataType) {
51
+ warningLog("exploreDataTypes! ignoring ",dataTypeNode.toString());
52
+ return;
53
+ }
54
+
46
55
  const namespaceIndex = dataType.namespace;
47
56
  consider(namespaceIndex);
48
57
  if (dataTypeNode.isStructure()) {
@@ -35,7 +35,6 @@ import { AttributeIds, Int64, minOPCUADate, StatusCode, StatusCodes } from "node
35
35
  import { BrowseDescription, EnumDefinition, StructureDefinition, StructureType } from "node-opcua-types";
36
36
 
37
37
  import { ITranslationTable, XmlWriter } from "../../source/xml_writer";
38
- import { NamespacePrivate } from "../namespace_private";
39
38
  import { ReferenceImpl } from "../reference_impl";
40
39
  import { BaseNodeImpl, getReferenceType } from "../base_node_impl";
41
40
  import { UAReferenceTypeImpl } from "../ua_reference_type_impl";
@@ -50,7 +49,11 @@ import { SessionContext } from "../index_current";
50
49
 
51
50
  import { DefinitionMap2, TypeInfo } from "../../source/loader/make_xml_extension_object_parser";
52
51
  import { makeDefinitionMap } from "../../source/loader/decode_xml_extension_object";
53
- import { constructNamespaceDependency, constructNamespacePriorityTable, hasHigherPriorityThan } from "./construct_namespace_dependency";
52
+ import {
53
+ constructNamespaceDependency,
54
+ constructNamespacePriorityTable,
55
+ hasHigherPriorityThan
56
+ } from "./construct_namespace_dependency";
54
57
 
55
58
  // tslint:disable:no-var-requires
56
59
  const XMLWriter = require("xml-writer");
@@ -247,6 +250,10 @@ function findXsdNamespaceUri(xw: XmlWriter, nodeId: NodeId): string {
247
250
  if (namespace === "http://opcfoundation.org/UA/") {
248
251
  return "http://opcfoundation.org/UA/2008/02/Types.xsd";
249
252
  }
253
+ // istanbul ignore next
254
+ if (!namespace) {
255
+ return "";
256
+ }
250
257
  return namespace.replace(/\/$/, "") + "/Types.xsd";
251
258
  }
252
259
 
@@ -628,37 +635,37 @@ function _dumpValue(xw: XmlWriter, node: UAVariable | UAVariableType, value: Var
628
635
  if (isExtensionObject) {
629
636
  const encodeXml = _dumpVariantExtensionObjectValue2.bind(null, xw, dataTypeNode);
630
637
 
631
- if (value.arrayType === VariantArrayType.Array) {
632
- startElementEx(xw, uax, `ListOf${baseDataTypeName}`, "http://opcfoundation.org/UA/2008/02/Types.xsd");
633
- value.value.forEach(encodeXml);
634
- restoreDefaultNamespace(xw);
635
- xw.endElement();
636
- } else if (value.arrayType === VariantArrayType.Scalar) {
637
- encodeXml(value.value);
638
- } else {
639
- errorLog(node.toString());
640
- errorLog("_dumpValue : unsupported case , Matrix of ExtensionObjects");
641
- // throw new Error("Unsupported case");
638
+ switch (value.arrayType) {
639
+ case VariantArrayType.Matrix:
640
+ case VariantArrayType.Array:
641
+ startElementEx(xw, uax, `ListOf${baseDataTypeName}`, "http://opcfoundation.org/UA/2008/02/Types.xsd");
642
+ value.value.forEach(encodeXml);
643
+ restoreDefaultNamespace(xw);
644
+ xw.endElement();
645
+ break;
646
+ case VariantArrayType.Scalar:
647
+ encodeXml(value.value);
648
+ break;
649
+ default:
650
+ errorLog(node.toString());
651
+ errorLog("_dumpValue : unsupported arrayType: ", value.arrayType);
642
652
  }
643
653
  } else {
644
654
  const encodeXml = _dumpVariantValue.bind(null, xw, value.dataType, node);
645
- if (value.arrayType === VariantArrayType.Matrix) {
646
- // console.log("Warning _dumpValue : Matrix not supported yet");
647
- startElementEx(xw, uax, `ListOf${dataTypeName}`, "http://opcfoundation.org/UA/2008/02/Types.xsd");
648
- value.value.forEach(encodeXml);
649
- restoreDefaultNamespace(xw);
650
- xw.endElement();
651
- } else if (value.arrayType === VariantArrayType.Array) {
652
- startElementEx(xw, uax, `ListOf${dataTypeName}`, "http://opcfoundation.org/UA/2008/02/Types.xsd");
653
- value.value.forEach(encodeXml);
654
- restoreDefaultNamespace(xw);
655
- xw.endElement();
656
- } else if (value.arrayType === VariantArrayType.Scalar) {
657
- encodeXml(value.value);
658
- } else {
659
- errorLog(node.toString());
660
- errorLog("_dumpValue : unsupported case , Matrix");
661
- // xx throw new Error("Unsupported case");
655
+ switch (value.arrayType) {
656
+ case VariantArrayType.Matrix:
657
+ case VariantArrayType.Array:
658
+ startElementEx(xw, uax, `ListOf${dataTypeName}`, "http://opcfoundation.org/UA/2008/02/Types.xsd");
659
+ value.value.forEach(encodeXml);
660
+ restoreDefaultNamespace(xw);
661
+ xw.endElement();
662
+ break;
663
+ case VariantArrayType.Scalar:
664
+ encodeXml(value.value);
665
+ break;
666
+ default:
667
+ errorLog(node.toString());
668
+ errorLog("_dumpValue : unsupported arrayType: ", value.arrayType);
662
669
  }
663
670
  }
664
671
 
@@ -675,7 +682,6 @@ function _dumpArrayDimensionsAttribute(xw: XmlWriter, node: UAVariableType | UAV
675
682
  }
676
683
 
677
684
  function visitUANode(node: BaseNode, data: DumpData, forward: boolean) {
678
-
679
685
  const addressSpace = node.addressSpace;
680
686
 
681
687
  // visit references
@@ -800,7 +806,7 @@ function dumpCommonAttributes(xw: XmlWriter, node: BaseNode) {
800
806
  }
801
807
  }
802
808
  if (Object.prototype.hasOwnProperty.call(node, "minimumSamplingInterval")) {
803
- const minimumSamplingInterval =(node as UAVariable).minimumSamplingInterval;
809
+ const minimumSamplingInterval = (node as UAVariable).minimumSamplingInterval;
804
810
  if (minimumSamplingInterval > 0) {
805
811
  xw.writeAttribute("MinimumSamplingInterval", minimumSamplingInterval);
806
812
  }
@@ -1030,11 +1036,11 @@ function dumpUAVariableType(xw: XmlWriter, node: UAVariableType) {
1030
1036
  // throw new Error(" cannot find datatype " + node.dataType);
1031
1037
  console.log(
1032
1038
  " cannot find datatype " +
1033
- node.dataType +
1034
- " for node " +
1035
- node.browseName.toString() +
1036
- " id =" +
1037
- node.nodeId.toString()
1039
+ node.dataType +
1040
+ " for node " +
1041
+ node.browseName.toString() +
1042
+ " id =" +
1043
+ node.nodeId.toString()
1038
1044
  );
1039
1045
  } else {
1040
1046
  const dataTypeName = b(xw, resolveDataTypeName(addressSpace, dataTypeNode.nodeId));
@@ -1063,6 +1069,7 @@ function dumpUAObject(xw: XmlWriter, node: UAObject) {
1063
1069
  _dumpUAObject(xw, node);
1064
1070
  xw.writeComment("Object - " + b(xw, node.browseName) + " }}}} ");
1065
1071
  }
1072
+
1066
1073
  function _dumpUAObject(xw: XmlWriter, node: UAObject) {
1067
1074
  assert(node.nodeClass === NodeClass.Object);
1068
1075
  xw.visitedNode = xw.visitedNode || {};
@@ -1101,9 +1108,7 @@ function dumpElementInFolder(xw: XmlWriter, node: BaseNodeImpl) {
1101
1108
 
1102
1109
  function dumpAggregates(xw: XmlWriter, node: BaseNode) {
1103
1110
  // Xx xw.writeComment("Aggregates {{ ");
1104
- const aggregates = node
1105
- .getAggregates()
1106
- .sort(sortByBrowseName);
1111
+ const aggregates = node.getAggregates().sort(sortByBrowseName);
1107
1112
  // const aggregates = node.findReferencesExAsObject("Aggregates", BrowseDirection.Forward);
1108
1113
 
1109
1114
  for (const aggregate of aggregates.sort(sortByNodeId)) {
@@ -1242,7 +1247,6 @@ function writeAliases(xw: XmlWriter, aliases: Record<string, NodeIdString>) {
1242
1247
  xw.endElement();
1243
1248
  }
1244
1249
 
1245
-
1246
1250
  export function constructNamespaceTranslationTable(dependency: INamespace[]): ITranslationTable {
1247
1251
  const translationTable: ITranslationTable = {};
1248
1252
  for (let i = 0; i < dependency.length; i++) {
@@ -1329,8 +1333,6 @@ function makeTypeXsd(namespaceUri: string): string {
1329
1333
 
1330
1334
  // eslint-disable-next-line max-statements
1331
1335
  NamespaceImpl.prototype.toNodeset2XML = function (this: NamespaceImpl) {
1332
-
1333
-
1334
1336
  const namespaceArrayNode = this.addressSpace.findNode(VariableIds.Server_NamespaceArray);
1335
1337
  const namespaceArray: string[] = namespaceArrayNode
1336
1338
  ? namespaceArrayNode.readAttribute(null, AttributeIds.Value).value.value
@@ -1343,7 +1345,6 @@ NamespaceImpl.prototype.toNodeset2XML = function (this: NamespaceImpl) {
1343
1345
  const translationTable = constructNamespaceTranslationTable(dependency);
1344
1346
  xw.translationTable = translationTable;
1345
1347
 
1346
-
1347
1348
  xw.startDocument({ encoding: "utf-8", version: "1.0" });
1348
1349
  xw.startElement("UANodeSet");
1349
1350
 
@@ -60,6 +60,11 @@ function _slow_isSupertypeOf<T extends UAType>(this: T, Class: typeof BaseNodeIm
60
60
 
61
61
  export type MemberFuncValue<T, P, R> = (this: T, param: P) => R;
62
62
 
63
+ export function wipeMemorizedStuff(node: any) {
64
+ if (!node.__cache) {
65
+ node.__cache = undefined;
66
+ }
67
+ }
63
68
  // http://jsperf.com/underscore-js-memoize-refactor-test
64
69
  // http://addyosmani.com/blog/faster-javascript-memoization/
65
70
  function wrap_memoize<T, P, R>(
@@ -1388,7 +1388,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1388
1388
  return false;
1389
1389
  }
1390
1390
  return checkExtensionObjectIsCorrectScalar.call(this, extObj);
1391
- } else if (this.valueRank === 1) {
1391
+ } else if (this.valueRank >= 1) {
1392
1392
  /** array */
1393
1393
  if (!(extObj instanceof Array)) {
1394
1394
  // let's coerce this scalar into an 1-element array if it is a valid extension object