@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.
package/build/src/compare/eq.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
19
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
102
|
-
|
|
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 {
|