node-opcua-address-space 2.66.2 → 2.68.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 (34) hide show
  1. package/dist/source/address_space_ts.d.ts +0 -2
  2. package/dist/source/address_space_ts.js.map +1 -1
  3. package/dist/source/continuation_points/continuation_point_manager.js +6 -3
  4. package/dist/source/continuation_points/continuation_point_manager.js.map +1 -1
  5. package/dist/source/loader/make_xml_extension_object_parser.js +28 -9
  6. package/dist/source/loader/make_xml_extension_object_parser.js.map +1 -1
  7. package/dist/src/base_node_impl.js +1 -1
  8. package/dist/src/base_node_impl.js.map +1 -1
  9. package/dist/src/extension_object_array_node.js +31 -22
  10. package/dist/src/extension_object_array_node.js.map +1 -1
  11. package/dist/src/historical_access/address_space_historical_data_node.js +3 -3
  12. package/dist/src/historical_access/address_space_historical_data_node.js.map +1 -1
  13. package/dist/src/reference_impl.js +1 -1
  14. package/dist/src/reference_impl.js.map +1 -1
  15. package/dist/src/ua_variable_impl.d.ts +9 -8
  16. package/dist/src/ua_variable_impl.js +56 -313
  17. package/dist/src/ua_variable_impl.js.map +1 -1
  18. package/dist/src/ua_variable_impl_ext_obj.d.ts +17 -0
  19. package/dist/src/ua_variable_impl_ext_obj.js +393 -0
  20. package/dist/src/ua_variable_impl_ext_obj.js.map +1 -0
  21. package/distNodeJS/generate_address_space.js +1 -1
  22. package/package.json +36 -36
  23. package/source/address_space_ts.ts +0 -2
  24. package/source/continuation_points/continuation_point_manager.ts +11 -9
  25. package/source/loader/make_xml_extension_object_parser.ts +32 -11
  26. package/source_nodejs/generate_address_space.ts +1 -1
  27. package/src/base_node_impl.ts +1 -1
  28. package/src/extension_object_array_node.ts +43 -28
  29. package/src/historical_access/address_space_historical_data_node.ts +3 -3
  30. package/src/reference_impl.ts +1 -1
  31. package/src/ua_variable_impl.ts +68 -381
  32. package/src/ua_variable_impl_ext_obj.ts +472 -0
  33. package/test_helpers/test_fixtures/issue_1132_variable_with_nodeid_value.xml +68 -0
  34. package/test_helpers/test_fixtures/nodeset_with_utf8_special_characters.xml +20 -0
@@ -9,6 +9,7 @@
9
9
  import * as chalk from "chalk";
10
10
 
11
11
  import {
12
+ BindExtensionObjectOptions,
12
13
  CloneExtraInfo,
13
14
  ContinuationData,
14
15
  defaultCloneExtraInfo,
@@ -80,7 +81,7 @@ import {
80
81
  BaseNode,
81
82
  UAVariableT
82
83
  } from "node-opcua-address-space-base";
83
- import { UAHistoricalDataConfiguration } from "node-opcua-nodeset-ua";
84
+ import { EnumFilterOperator, UAHistoricalDataConfiguration } from "node-opcua-nodeset-ua";
84
85
 
85
86
  import { SessionContext } from "../source/session_context";
86
87
  import { convertToCallbackFunction1 } from "../source/helpers/multiform_func";
@@ -88,6 +89,7 @@ import { BaseNodeImpl, InternalBaseNodeOptions } from "./base_node_impl";
88
89
  import { _clone, ToStringBuilder, UAVariable_toString, valueRankToString } from "./base_node_private";
89
90
  import { EnumerationInfo, IEnumItem, UADataTypeImpl } from "./ua_data_type_impl";
90
91
  import { apply_condition_refresh, ConditionRefreshCache } from "./apply_condition_refresh";
92
+ import { extractPartialData, propagateTouchValueUpward, setExtensionObjectValue, _bindExtensionObject, _installExtensionObjectBindingOnProperties, _setExtensionObject, _touchValue } from "./ua_variable_impl_ext_obj";
91
93
 
92
94
  const debugLog = make_debugLog(__filename);
93
95
  const warningLog = make_warningLog(__filename);
@@ -157,7 +159,6 @@ function _dataType_toUADataType(addressSpace: IAddressSpace, dataType: DataType)
157
159
  }
158
160
  return dataTypeNode as UADataType;
159
161
  }
160
-
161
162
  /*=
162
163
  *
163
164
  * @param addressSpace
@@ -681,7 +682,8 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
681
682
  if (
682
683
  this.dataType.namespace === 0 &&
683
684
  this.dataType.value === DataType.LocalizedText &&
684
- variant.dataType !== DataType.LocalizedText && variant.dataType !== DataType.Null
685
+ variant.dataType !== DataType.LocalizedText &&
686
+ variant.dataType !== DataType.Null
685
687
  ) {
686
688
  throw new Error(
687
689
  "Variant must provide a valid LocalizedText : variant = " +
@@ -699,7 +701,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
699
701
  if (basicType === DataType.ByteString && variant.dataType === DataType.String) {
700
702
  return; // this is allowed
701
703
  }
702
-
704
+
703
705
  if (
704
706
  basicType !== DataType.Null &&
705
707
  basicType !== DataType.Variant &&
@@ -757,7 +759,22 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
757
759
  dataValue.sourceTimestamp = now.timestamp;
758
760
  dataValue.statusCode = statusCode;
759
761
  dataValue.value = variant1;
760
- this._internal_set_dataValue(dataValue);
762
+
763
+ if (dataValue.value.dataType === DataType.ExtensionObject) {
764
+ this.$dataValue = dataValue;
765
+ assert(this.checkExtensionObjectIsCorrect(dataValue.value.value));
766
+ // ----------------------------------
767
+ if (this.$extensionObject) {
768
+ // we have an extension object already bound to this node
769
+ // the client is asking us to replace the object entierly by a new one
770
+ const ext = dataValue.value.value;
771
+ _setExtensionObject(this, ext);
772
+ return;
773
+ }
774
+ } else {
775
+ this._internal_set_dataValue(dataValue);
776
+ }
777
+
761
778
  } catch (err) {
762
779
  errorLog("UAVariable#setValueFromString Error : ", this.browseName.toString(), this.nodeId.toString());
763
780
  errorLog((err as Error).message);
@@ -981,32 +998,12 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
981
998
  }
982
999
 
983
1000
  /**
984
- * @method touchValue
985
1001
  * touch the source timestamp of a Variable and cascade up the change
986
1002
  * to the parent variable if any.
987
- *
988
- * @param [optionalNow=null] {Object}
989
- * @param optionalNow.timestamp {Date}
990
- * @param optionalNow.picoseconds {Number}
991
1003
  */
992
1004
  public touchValue(optionalNow?: PreciseClock): void {
993
1005
  const now = optionalNow || getCurrentClock();
994
- this.$dataValue.sourceTimestamp = now.timestamp;
995
- this.$dataValue.sourcePicoseconds = now.picoseconds;
996
- this.$dataValue.serverTimestamp = now.timestamp;
997
- this.$dataValue.serverPicoseconds = now.picoseconds;
998
-
999
- this.$dataValue.statusCode = StatusCodes.Good;
1000
-
1001
- if (this.minimumSamplingInterval === 0) {
1002
- if (this.listenerCount("value_changed") > 0) {
1003
- const clonedDataValue = this.readValue();
1004
- this.emit("value_changed", clonedDataValue);
1005
- }
1006
- }
1007
- if (this.parent && this.parent.nodeClass === NodeClass.Variable) {
1008
- (this.parent as UAVariable).touchValue(now);
1009
- }
1006
+ propagateTouchValueUpward(this, now);
1010
1007
  }
1011
1008
 
1012
1009
  /**
@@ -1170,7 +1167,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1170
1167
  if (!context) {
1171
1168
  context = SessionContext.defaultContext;
1172
1169
  }
1173
- assert(callback instanceof Function);
1170
+ assert(typeof callback === 'function');
1174
1171
 
1175
1172
  this.__waiting_callbacks = this.__waiting_callbacks || [];
1176
1173
  this.__waiting_callbacks.push(callback);
@@ -1263,6 +1260,12 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1263
1260
 
1264
1261
  assert(newVariable.dataType === this.dataType);
1265
1262
  newVariable.$dataValue = this.$dataValue.clone();
1263
+
1264
+ // also bind extension object
1265
+ const v = newVariable.$dataValue.value;
1266
+ if (v.dataType === DataType.ExtensionObject && v.value && v.arrayType === VariantArrayType.Scalar) {
1267
+ newVariable.bindExtensionObject(newVariable.$dataValue.value.value);
1268
+ }
1266
1269
  return newVariable;
1267
1270
  }
1268
1271
 
@@ -1318,281 +1321,35 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1318
1321
  return false;
1319
1322
  }
1320
1323
  }
1324
+
1321
1325
  /**
1322
- * @method bindExtensionObject
1323
- * @return {ExtensionObject}
1326
+ * @private
1327
+ * install UAVariable to exposed th
1328
+ *
1329
+ * precondition:
1324
1330
  */
1325
- public bindExtensionObject(optionalExtensionObject?: ExtensionObject): ExtensionObject | null {
1326
- const addressSpace = this.addressSpace;
1327
- const structure = addressSpace.findDataType("Structure");
1328
- let extensionObject_;
1329
-
1330
- if (!structure) {
1331
- // the addressSpace is limited and doesn't provide extension object
1332
- // bindExtensionObject cannot be performed and shall finish here.
1333
- return null;
1334
- }
1335
-
1336
- // istanbul ignore next
1337
- if (doDebug) {
1338
- debugLog(" ------------------------------ binding ", this.browseName.toString(), this.nodeId.toString());
1339
- }
1340
- assert(structure && structure.browseName.toString() === "Structure", "expecting DataType Structure to be in IAddressSpace");
1341
-
1342
- const dt = this.getDataTypeNode() as UADataTypeImpl;
1343
- if (!dt.isSupertypeOf(structure)) {
1344
- return null;
1345
- }
1346
-
1347
- // the namespace for the structure browse name elements
1348
- const structureNamespace = dt.nodeId.namespace;
1349
-
1350
- // -------------------- make sure we do not bind a variable twice ....
1351
- if (this.$extensionObject) {
1352
- // istanbul ignore next
1353
- // if (!force && !utils.isNullOrUndefined(optionalExtensionObject)) {
1354
- // throw new Error(
1355
- // "bindExtensionObject: unsupported case : $extensionObject already exists on " +
1356
- // this.browseName.toString() +
1357
- // " " +
1358
- // this.nodeId.toString()
1359
- // );
1360
- // }
1361
- // istanbul ignore next
1362
- if (!this.checkExtensionObjectIsCorrect(this.$extensionObject!)) {
1363
- warningLog(
1364
- "on node : ",
1365
- this.browseName.toString(),
1366
- this.nodeId.toString(),
1367
- "dataType=",
1368
- this.dataType.toString({ addressSpace: this.addressSpace })
1369
- );
1370
- warningLog(this.$extensionObject?.toString());
1371
- throw new Error(
1372
- "bindExtensionObject: $extensionObject is incorrect: we are expecting a " +
1373
- this.dataType.toString({ addressSpace: this.addressSpace }) +
1374
- " but we got a " +
1375
- this.$extensionObject?.constructor.name
1376
- );
1377
- }
1378
- return this.$extensionObject;
1379
- // throw new Error("Variable already bound");
1380
- }
1381
- this.$extensionObject = optionalExtensionObject;
1382
-
1383
- // ------------------------------------------------------------------
1384
-
1385
- function prepareVariantValue(dataType: DataType, value: VariantLike): VariantLike {
1386
- if ((dataType === DataType.Int32 || dataType === DataType.UInt32) && value && (value as any).key) {
1387
- value = value.value;
1388
- }
1389
- return value;
1390
- }
1391
-
1392
- const bindProperty = (propertyNode: UAVariableImpl, name: string, extensionObject: ExtensionObject, dataType: DataType) => {
1393
- // eslint-disable-next-line @typescript-eslint/no-this-alias
1394
- const self = this;
1395
- propertyNode.bindVariable(
1396
- {
1397
- timestamped_get: () => {
1398
- const propertyValue = self.$extensionObject[name];
1399
-
1400
- if (propertyValue === undefined) {
1401
- propertyNode.$dataValue.value.dataType = DataType.Null;
1402
- propertyNode.$dataValue.statusCode = StatusCodes.Good;
1403
- propertyNode.$dataValue.value.value = null;
1404
- return new DataValue(propertyNode.$dataValue);
1405
- }
1406
- const value = prepareVariantValue(dataType, propertyValue);
1407
- propertyNode.$dataValue.statusCode = StatusCodes.Good;
1408
- propertyNode.$dataValue.value.dataType = dataType;
1409
- propertyNode.$dataValue.value.value = value;
1410
- return new DataValue(propertyNode.$dataValue);
1411
- },
1412
- timestamped_set: (dataValue: DataValue, callback: CallbackT<StatusCode>) => {
1413
- dataValue;
1414
- callback(null, StatusCodes.BadNotWritable);
1415
- }
1416
- },
1417
- true
1418
- );
1419
- };
1420
- const components = this.getComponents();
1421
-
1422
- // ------------------------------------------------------
1423
- // make sure we have a structure
1424
- // ------------------------------------------------------
1425
- const s = this.readValue();
1426
- // istanbul ignore next
1427
- if (this.dataTypeObj.isAbstract) {
1428
- warningLog("Warning the DataType associated with this Variable is abstract ", this.dataTypeObj.browseName.toString());
1429
- warningLog("You need to provide a extension object yourself ");
1430
- throw new Error("bindExtensionObject requires a extensionObject as associated dataType is only abstract");
1431
- }
1432
- if (s.value && (s.value.dataType === DataType.Null || (s.value.dataType === DataType.ExtensionObject && !s.value.value))) {
1433
- // create a structure and bind it
1434
- extensionObject_ = this.$extensionObject || addressSpace.constructExtensionObject(this.dataType, {});
1435
- extensionObject_ = new Proxy(extensionObject_, makeHandler(this));
1436
- this.$extensionObject = extensionObject_;
1437
-
1438
- const theValue = new Variant({
1439
- dataType: DataType.ExtensionObject,
1440
- value: this.$extensionObject
1441
- });
1442
- this.setValueFromSource(theValue, StatusCodes.Good);
1443
-
1444
- // eslint-disable-next-line @typescript-eslint/no-this-alias
1445
- const self = this;
1446
- this.bindVariable(
1447
- {
1448
- timestamped_get() {
1449
- self.$dataValue.value.value = self.$extensionObject;
1450
- const d = new DataValue(self.$dataValue);
1451
- d.value = new Variant(d.value);
1452
- return d;
1453
- },
1454
- timestamped_set(dataValue: DataValue, callback: CallbackT<StatusCode>) {
1455
- const ext = dataValue.value.value;
1456
- if (!self.checkExtensionObjectIsCorrect(ext)) {
1457
- return callback(null, StatusCodes.BadInvalidArgument);
1458
- }
1459
- self.$extensionObject = new Proxy(ext, makeHandler(self));
1460
- self.touchValue();
1461
- callback(null, StatusCodes.Good);
1462
- }
1463
- },
1464
- true
1465
- );
1466
- } else {
1467
- // verify that variant has the correct type
1468
- assert(s.value.dataType === DataType.ExtensionObject);
1469
- this.$extensionObject = s.value.value;
1470
- assert(this.checkExtensionObjectIsCorrect(this.$extensionObject!));
1471
- assert(s.statusCode.equals(StatusCodes.Good));
1472
- }
1473
-
1474
- // ------------------------------------------------------
1475
- // now bind each member
1476
- // ------------------------------------------------------
1477
- const definition = dt._getDefinition() as StructureDefinition | null;
1478
-
1479
- // istanbul ignore next
1480
- if (!definition) {
1481
- throw new Error("xx definition missing in " + dt.toString());
1482
- }
1483
-
1484
- const getOrCreateProperty = (field: StructureField): UAVariableImpl => {
1485
- let property: UAVariableImpl;
1486
- const selectedComponents = components.filter(
1487
- (f) => f instanceof UAVariableImpl && f.browseName.name!.toString() === field.name
1488
- );
1489
-
1490
- if (field.dataType.value === DataType.Variant) {
1491
- warningLog("Warning : variant is not supported in ExtensionObject");
1492
- }
1493
- if (selectedComponents.length === 1) {
1494
- property = selectedComponents[0] as UAVariableImpl;
1495
- /* istanbul ignore next */
1496
- } else {
1497
- debugLog("adding missing array variable", field.name, this.browseName.toString(), this.nodeId.toString());
1498
- // todo: Handle array appropriately...
1499
- assert(selectedComponents.length === 0);
1500
- // create a variable (Note we may use ns=1;s=parentName/0:PropertyName)
1501
- property = this.namespace.addVariable({
1502
- browseName: { namespaceIndex: structureNamespace, name: field.name!.toString() },
1503
- componentOf: this,
1504
- dataType: field.dataType,
1505
- minimumSamplingInterval: this.minimumSamplingInterval
1506
- }) as UAVariableImpl;
1507
- assert(property.minimumSamplingInterval === this.minimumSamplingInterval);
1508
- }
1509
- return property;
1510
- };
1511
-
1512
- for (const field of definition.fields || []) {
1513
- if (NodeId.sameNodeId(NodeId.nullNodeId, field.dataType)) {
1514
- warningLog("field.dataType is null ! ", field.toString(), NodeId.nullNodeId.toString());
1515
- warningLog(" dataType replaced with BaseDataType ");
1516
- warningLog(definition.toString());
1517
- field.dataType = this.resolveNodeId("BaseDataType");
1518
- }
1519
-
1520
- const camelCaseName = lowerFirstLetter(field.name!);
1521
- assert(Object.prototype.hasOwnProperty.call(this.$extensionObject, camelCaseName));
1522
-
1523
- const propertyNode = getOrCreateProperty(field);
1524
-
1525
- propertyNode.$dataValue.statusCode = StatusCodes.Good;
1526
- propertyNode.touchValue();
1527
-
1528
- const basicDataType = addressSpace.findCorrespondingBasicDataType(field.dataType);
1529
-
1530
- // istanbul ignore next
1531
- if (doDebug) {
1532
- const x = addressSpace.findNode(field.dataType)!.browseName.toString();
1533
- debugLog(
1534
- chalk.cyan("xxx"),
1535
- " dataType",
1536
- w(field.dataType.toString(), 8),
1537
- w(field.name!, 35),
1538
- "valueRank",
1539
- chalk.cyan(w(valueRankToString(field.valueRank), 10)),
1540
- chalk.green(w(x, 25)),
1541
- "basicType = ",
1542
- chalk.yellow(w(basicDataType.toString(), 20)),
1543
- propertyNode.nodeId.toString(),
1544
- propertyNode.readValue().statusCode.toString()
1545
- );
1546
- }
1547
- if (this.$extensionObject[camelCaseName] !== undefined && basicDataType === DataType.ExtensionObject) {
1548
- assert(this.$extensionObject[camelCaseName] instanceof Object);
1549
- this.$extensionObject[camelCaseName] = new Proxy(this.$extensionObject[camelCaseName], makeHandler(propertyNode));
1550
-
1551
- propertyNode._internal_set_value(
1552
- new Variant({
1553
- dataType: DataType.ExtensionObject,
1554
- value: this.$extensionObject[camelCaseName]
1555
- })
1556
- );
1557
-
1558
- propertyNode.bindExtensionObject();
1559
- propertyNode.$extensionObject = this.$extensionObject[camelCaseName];
1560
- } else {
1561
- const prop = this.$extensionObject[camelCaseName];
1562
- if (prop === undefined) {
1563
- propertyNode._internal_set_value(
1564
- new Variant({
1565
- dataType: DataType.Null
1566
- })
1567
- );
1568
- } else {
1569
- const preparedValue = prepareVariantValue(basicDataType, prop);
1570
- propertyNode._internal_set_value(
1571
- new Variant({
1572
- dataType: basicDataType,
1573
- value: preparedValue
1574
- })
1575
- );
1331
+ public installExtensionObjectVariables(): void {
1332
+ _installExtensionObjectBindingOnProperties(this, { createMissingProp: true });
1333
+ // now recursively install extension object on children
1334
+ for (const child of this.getComponents()) {
1335
+ if (child.nodeClass === NodeClass.Variable && child instanceof UAVariableImpl) {
1336
+ if (child.isExtensionObject()) {
1337
+ child.installExtensionObjectVariables();
1576
1338
  }
1577
-
1578
- // eslint-disable-next-line @typescript-eslint/no-this-alias
1579
- const self = this;
1580
- // property.camelCaseName = camelCaseName;
1581
- propertyNode.setValueFromSource = function (this: UAVariableImpl, variant: VariantLike) {
1582
- // eslint-disable-next-line @typescript-eslint/no-this-alias
1583
- const inner_this = this;
1584
- const variant1 = Variant.coerce(variant);
1585
- inner_this.verifyVariantCompatibility(variant1);
1586
- self.$extensionObject[camelCaseName] = variant1.value;
1587
- self.touchValue();
1588
- };
1589
1339
  }
1590
- assert(propertyNode.readValue().statusCode.equals(StatusCodes.Good));
1591
- bindProperty(propertyNode, camelCaseName, this.$extensionObject, basicDataType);
1592
1340
  }
1593
- assert(this.$extensionObject instanceof Object);
1594
- return this.$extensionObject;
1595
1341
  }
1342
+ /**
1343
+ * @method bindExtensionObject
1344
+ * @return {ExtensionObject}
1345
+ */
1346
+ public bindExtensionObject(
1347
+ optionalExtensionObject?: ExtensionObject,
1348
+ options?: BindExtensionObjectOptions
1349
+ ): ExtensionObject | null {
1350
+ return _bindExtensionObject(this, optionalExtensionObject, options);
1351
+ }
1352
+
1596
1353
 
1597
1354
  public updateExtensionObjectPartial(partialExtensionObject?: { [key: string]: any }): ExtensionObject {
1598
1355
  setExtensionObjectValue(this, partialExtensionObject);
@@ -1600,43 +1357,11 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1600
1357
  }
1601
1358
 
1602
1359
  public incrementExtensionObjectPartial(path: string | string[]): void {
1603
- let name;
1604
- if (typeof path === "string") {
1605
- path = path.split(".");
1606
- }
1607
- assert(path instanceof Array);
1608
- const extensionObject = this.constructExtensionObjectFromComponents();
1609
- let i;
1610
- // read partial value
1611
- const partialData: any = {};
1612
- let p: any = partialData;
1613
- for (i = 0; i < path.length - 1; i++) {
1614
- name = path[i];
1615
- p[name] = {};
1616
- p = p[name];
1617
- }
1618
- name = path[path.length - 1];
1619
- p[name] = 0;
1620
-
1621
- let c1 = partialData;
1622
- let c2 = extensionObject;
1623
-
1624
- for (i = 0; i < path.length - 1; i++) {
1625
- name = path[i];
1626
- c1 = partialData[name];
1627
- c2 = extensionObject[name];
1628
- }
1629
- name = path[path.length - 1];
1630
- c1[name] = c2[name];
1631
- c1[name] += 1;
1632
-
1360
+ const extensionObject = this.readValue().value.value as ExtensionObject;
1361
+ const partialData = extractPartialData(path, extensionObject);
1633
1362
  setExtensionObjectValue(this, partialData);
1634
1363
  }
1635
1364
 
1636
- public constructExtensionObjectFromComponents(): any {
1637
- return this.readValue().value.value;
1638
- }
1639
-
1640
1365
  public toString(): string {
1641
1366
  const options = new ToStringBuilder();
1642
1367
  UAVariable_toString.call(this, options);
@@ -1687,7 +1412,7 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1687
1412
  callback?: CallbackT<HistoryReadResult>
1688
1413
  ): any {
1689
1414
  assert(context instanceof SessionContext);
1690
- assert(callback instanceof Function);
1415
+ assert(typeof callback === 'function');
1691
1416
  if (typeof this._historyRead !== "function") {
1692
1417
  return callback!(null, new HistoryReadResult({ statusCode: StatusCodes.BadNotReadable }));
1693
1418
  }
@@ -1779,14 +1504,15 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1779
1504
  }
1780
1505
  this.$dataValue.value = value;
1781
1506
  }
1507
+
1508
+
1782
1509
  public _internal_set_dataValue(dataValue: DataValue, indexRange?: NumericRange | null): void {
1783
1510
  assert(dataValue, "expecting a dataValue");
1784
1511
  assert(dataValue instanceof DataValue, "expecting dataValue to be a DataValue");
1785
1512
  assert(dataValue !== this.$dataValue, "expecting dataValue to be different from previous DataValue instance");
1786
-
1787
1513
 
1788
1514
  const addressSpace = this.addressSpace;
1789
- if(!addressSpace) {
1515
+ if (!addressSpace) {
1790
1516
  warningLog("UAVariable#_internal_set_dataValue : no addressSpace ! may be node has already been deleted ?");
1791
1517
  return;
1792
1518
  }
@@ -1808,6 +1534,14 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
1808
1534
  warningLog(dataValue.toString());
1809
1535
  throw new Error("Invalid Extension Object on nodeId =" + this.nodeId.toString());
1810
1536
  }
1537
+ // ----------------------------------
1538
+ // if (this.$extensionObject) {
1539
+ // // we have an extension object already bound to this node
1540
+ // // the client is asking us to replace the object entierly by a new one
1541
+ // const ext = dataValue.value.value;
1542
+ // _setExtensionObject(this, ext);
1543
+ // return;
1544
+ // }
1811
1545
  }
1812
1546
  // // istanbul ignore next
1813
1547
  // if (this.dataType.namespace === 0) {
@@ -1952,6 +1686,7 @@ export interface UAVariableImpl {
1952
1686
  $$indexPropertyName: any;
1953
1687
  }
1954
1688
 
1689
+
1955
1690
  function check_valid_array(dataType: DataType, array: any): boolean {
1956
1691
  if (Array.isArray(array)) {
1957
1692
  return true;
@@ -2307,54 +2042,6 @@ function bind_getter(this: UAVariableImpl, options: GetterOptions) {
2307
2042
  }
2308
2043
  }
2309
2044
 
2310
- function w(str: string, n: number): string {
2311
- return (str + " ").substr(0, n);
2312
- }
2313
-
2314
- function _getter(target: any, key: string /*, receiver*/) {
2315
- if (target[key] === undefined) {
2316
- return undefined;
2317
- }
2318
- return target[key];
2319
- }
2320
-
2321
- function _setter(variable: UAVariable, target: any, key: string, value: any /*, receiver*/) {
2322
- target[key] = value;
2323
- const child = (variable as any)[key] as UAVariable | null;
2324
- if (child && child.touchValue) {
2325
- child.touchValue();
2326
- }
2327
- return true; // true means the set operation has succeeded
2328
- }
2329
-
2330
- function makeHandler(variable: UAVariable) {
2331
- const handler = {
2332
- get: _getter,
2333
- set: _setter.bind(null, variable)
2334
- };
2335
- return handler;
2336
- }
2337
-
2338
- function setExtensionObjectValue(node: UAVariableImpl, partialObject: any) {
2339
- const extensionObject = node.$extensionObject;
2340
- if (!extensionObject) {
2341
- throw new Error("setExtensionObjectValue node has no extension object " + node.browseName.toString());
2342
- }
2343
-
2344
- function _update_extension_object(extObject: any, partialObject1: any) {
2345
- const keys = Object.keys(partialObject1);
2346
- for (const prop of keys) {
2347
- if (extObject[prop] instanceof Object) {
2348
- _update_extension_object(extObject[prop], partialObject1[prop]);
2349
- } else {
2350
- extObject[prop] = partialObject1[prop];
2351
- }
2352
- }
2353
- }
2354
-
2355
- _update_extension_object(extensionObject, partialObject);
2356
- }
2357
-
2358
2045
  export interface UAVariableImplT<T, DT extends DataType> extends UAVariableImpl, UAVariableT<T, DT> {
2359
2046
  on(): any;
2360
2047
  once(): any;