@abaplint/runtime 2.13.40 → 2.13.42

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.
@@ -19,11 +19,104 @@ function compareTables(left, right) {
19
19
  }
20
20
  return true;
21
21
  }
22
+ function compareStructures(left, right) {
23
+ const l = left.get();
24
+ const r = right.get();
25
+ const leftKeys = Object.keys(l);
26
+ const rightKeys = Object.keys(r);
27
+ if (leftKeys.length !== rightKeys.length) {
28
+ return false;
29
+ }
30
+ for (const k of leftKeys) {
31
+ const e = eq(l[k], r[k]);
32
+ if (e === false) {
33
+ return false;
34
+ }
35
+ }
36
+ return true;
37
+ }
38
+ // module locals instead of the imported bindings, as the CommonJS re-export
39
+ // getters add overhead on every access in the hot path below
40
+ const IntegerC = types_1.Integer;
41
+ const StringC = types_1.String;
42
+ const CharacterC = types_1.Character;
43
+ const NumcC = types_1.Numc;
44
+ const DateC = types_1.Date;
45
+ const TimeC = types_1.Time;
46
+ const PackedC = types_1.Packed;
47
+ const FloatC = types_1.Float;
48
+ const TableC = types_1.Table;
49
+ const HashedTableC = types_1.HashedTable;
50
+ const StructureC = types_1.Structure;
51
+ const XStringC = types_1.XString;
52
+ const HexC = types_1.Hex;
53
+ const HexUInt8C = types_1.HexUInt8;
54
+ const Integer8C = types_1.Integer8;
55
+ const ABAPObjectC = types_1.ABAPObject;
56
+ const DataReferenceC = types_1.DataReference;
22
57
  function eq(left, right) {
23
58
  /*
24
59
  console.dir(left);
25
60
  console.dir(right);
26
61
  */
62
+ // fast path: same concrete type covers the vast majority of comparisons,
63
+ // exact constructor identity, so subclasses and other types fall through
64
+ const leftConstructor = left?.constructor;
65
+ if (leftConstructor === right?.constructor) {
66
+ if (leftConstructor === IntegerC) {
67
+ return left.get() === right.get();
68
+ }
69
+ else if (leftConstructor === StringC) {
70
+ return left.get() === right.get();
71
+ }
72
+ else if (leftConstructor === CharacterC) {
73
+ if (left.getLength() === right.getLength()) {
74
+ return left.get() === right.get();
75
+ }
76
+ else {
77
+ return left.getTrimEnd() === right.getTrimEnd();
78
+ }
79
+ }
80
+ else if (leftConstructor === NumcC) {
81
+ return left.get() === right.get();
82
+ }
83
+ else if (leftConstructor === DateC) {
84
+ return left.get() === right.get();
85
+ }
86
+ else if (leftConstructor === TimeC) {
87
+ return left.get() === right.get();
88
+ }
89
+ else if (leftConstructor === PackedC) {
90
+ return left.get() === right.get();
91
+ }
92
+ else if (leftConstructor === FloatC) {
93
+ return left.getRaw() === right.getRaw();
94
+ }
95
+ else if (leftConstructor === TableC || leftConstructor === HashedTableC) {
96
+ return compareTables(left, right);
97
+ }
98
+ else if (leftConstructor === StructureC) {
99
+ return compareStructures(left, right);
100
+ }
101
+ else if (leftConstructor === XStringC) {
102
+ return left.get() === right.get();
103
+ }
104
+ else if (leftConstructor === HexC || leftConstructor === HexUInt8C) {
105
+ if (left.getLength() !== right.getLength()) {
106
+ return (0, initial_1.initial)(left) && (0, initial_1.initial)(right);
107
+ }
108
+ return left.get() === right.get();
109
+ }
110
+ else if (leftConstructor === Integer8C) {
111
+ return left.get() === right.get();
112
+ }
113
+ else if (leftConstructor === ABAPObjectC) {
114
+ return left.get() === right.get();
115
+ }
116
+ else if (leftConstructor === DataReferenceC) {
117
+ return left.getPointer() === right.getPointer();
118
+ }
119
+ }
27
120
  if (right instanceof types_1.FieldSymbol) {
28
121
  return eq(left, right.getPointer());
29
122
  }
@@ -186,20 +279,7 @@ function eq(left, right) {
186
279
  else if (!(left instanceof types_1.Structure)) {
187
280
  return eq(left, right.getCharacter());
188
281
  }
189
- const l = left.get();
190
- const r = right.get();
191
- const leftKeys = Object.keys(l);
192
- const rightKeys = Object.keys(r);
193
- if (leftKeys.length !== rightKeys.length) {
194
- return false;
195
- }
196
- for (const k of leftKeys) {
197
- const e = eq(l[k], r[k]);
198
- if (e === false) {
199
- return false;
200
- }
201
- }
202
- return true;
282
+ return compareStructures(left, right);
203
283
  }
204
284
  let l = undefined;
205
285
  if (left instanceof types_1.Character) {
@@ -12,7 +12,7 @@ export declare class Structure {
12
12
  private readonly asInclude;
13
13
  constructor(fields: {
14
14
  [key: string]: any;
15
- }, qualifiedName?: string, ddicName?: string, suffix?: any, asInclude?: any);
15
+ }, qualifiedName?: string, ddicName?: string, suffix?: any, asInclude?: any, cloning?: boolean);
16
16
  private linkGroupFields;
17
17
  clone(): Structure;
18
18
  clear(): this;
@@ -7,19 +7,39 @@ const _parse_1 = require("../operators/_parse");
7
7
  const character_1 = require("./character");
8
8
  const throw_error_1 = require("../throw_error");
9
9
  const abap_object_1 = require("./abap_object");
10
+ // structures are typically instantiated repeatedly with the same literal names,
11
+ // cache the uppercasing
12
+ const upperCaseCache = new Map();
13
+ function cachedUpperCase(name) {
14
+ let upper = upperCaseCache.get(name);
15
+ if (upper === undefined) {
16
+ upper = name.toUpperCase();
17
+ upperCaseCache.set(name, upper);
18
+ }
19
+ return upper;
20
+ }
10
21
  class Structure {
11
22
  value;
12
23
  qualifiedName;
13
24
  ddicName;
14
25
  suffix;
15
26
  asInclude;
16
- constructor(fields, qualifiedName, ddicName, suffix, asInclude) {
27
+ // "cloning = true" is only used from clone(), the names are then already uppercased
28
+ constructor(fields, qualifiedName, ddicName, suffix, asInclude, cloning = false) {
17
29
  this.value = fields;
18
- this.qualifiedName = qualifiedName?.toUpperCase();
19
- this.ddicName = ddicName?.toUpperCase();
30
+ if (cloning === true) {
31
+ this.qualifiedName = qualifiedName;
32
+ this.ddicName = ddicName;
33
+ }
34
+ else {
35
+ this.qualifiedName = qualifiedName === undefined ? undefined : cachedUpperCase(qualifiedName);
36
+ this.ddicName = ddicName === undefined ? undefined : cachedUpperCase(ddicName);
37
+ }
20
38
  this.suffix = suffix;
21
39
  this.asInclude = asInclude;
22
- this.linkGroupFields();
40
+ if (asInclude !== undefined) {
41
+ this.linkGroupFields();
42
+ }
23
43
  }
24
44
  linkGroupFields() {
25
45
  for (const as of Object.keys(this.asInclude || {})) {
@@ -34,7 +54,9 @@ class Structure {
34
54
  for (const key in this.value) {
35
55
  newValues[key] = this.value[key].clone();
36
56
  }
37
- const n = new Structure(newValues, this.qualifiedName, this.ddicName, this.suffix, this.asInclude);
57
+ // note: when includes are present, the constructor re-links the group
58
+ // fields so they alias the cloned include's fields
59
+ const n = new Structure(newValues, this.qualifiedName, this.ddicName, this.suffix, this.asInclude, true);
38
60
  return n;
39
61
  }
40
62
  clear() {
@@ -98,8 +120,15 @@ class Structure {
98
120
  if (this.value[key2] === undefined) {
99
121
  break;
100
122
  }
101
- // todo: can clone() be removed? might be needed for like Structure and Tables?
102
- this.value[key2].set(obj[key1].clone());
123
+ const val = obj[key1];
124
+ if (val instanceof Structure || val instanceof table_1.Table || val instanceof table_1.HashedTable) {
125
+ // deep types are cloned so the target never shares references with the source
126
+ this.value[key2].set(val.clone());
127
+ }
128
+ else {
129
+ // elementary types copy by value in set(), no clone needed
130
+ this.value[key2].set(val);
131
+ }
103
132
  }
104
133
  }
105
134
  else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/runtime",
3
- "version": "2.13.40",
3
+ "version": "2.13.42",
4
4
  "description": "Transpiler - Runtime",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/src/index.d.ts",