@abaplint/runtime 2.13.49 → 2.13.51

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.
@@ -17,19 +17,22 @@ function concatenate(input) {
17
17
  }
18
18
  }
19
19
  if (input.lines === true) {
20
- const list = [];
20
+ let result = "";
21
21
  const tab = input.source[0];
22
22
  if (tab instanceof types_1.Table) {
23
- for (const l of tab.array()) {
24
- if (input.respectingBlanks !== true) {
25
- list.push(l.get().trimEnd());
26
- }
27
- else {
28
- list.push(l.get());
23
+ const array = tab.array();
24
+ const length = array.length;
25
+ const respectingBlanks = input.respectingBlanks === true;
26
+ const hasSeparator = sep.length > 0;
27
+ for (let i = 0; i < length; i++) {
28
+ if (hasSeparator === true && i > 0) {
29
+ result += sep;
29
30
  }
31
+ const value = array[i].get();
32
+ result += respectingBlanks === true ? value : value.trimEnd();
30
33
  }
31
34
  }
32
- input.target.set(list.join(sep));
35
+ input.target.set(result);
33
36
  }
34
37
  else {
35
38
  let result = "";
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.insertInternal = insertInternal;
4
- const compare_1 = require("../compare");
5
4
  const types_1 = require("../types");
6
- const read_table_1 = require("./read_table");
7
5
  const sort_1 = require("./sort");
8
6
  function insertInternal(options) {
9
7
  if (options.table instanceof types_1.FieldSymbol) {
@@ -18,60 +16,34 @@ function insertInternal(options) {
18
16
  }
19
17
  options.data = options.data.getPointer();
20
18
  }
19
+ let data = options.data;
20
+ if (typeof data === "string") {
21
+ const tmp = options.table.getRowType().clone();
22
+ tmp.set(data);
23
+ data = tmp;
24
+ }
21
25
  const tableOptions = options.table.getOptions();
22
- let isSorted = tableOptions?.primaryKey?.type === types_1.TableAccessType.sorted
26
+ const isSorted = tableOptions?.primaryKey?.type === types_1.TableAccessType.sorted
23
27
  || tableOptions?.primaryKey?.type === types_1.TableAccessType.hashed;
24
- if (options.table instanceof types_1.HashedTable) {
25
- isSorted = false;
26
- }
27
- else if (isSorted) {
28
- const insert = options.data instanceof types_1.Structure ? options.data.get() : { table_line: options.data };
29
- let compare = (row) => {
30
- for (const key of tableOptions?.primaryKey?.keyFields || []) {
31
- if (key.includes("-")) {
32
- const [first, second] = key.split("-");
33
- if ((0, compare_1.ne)(row[first.toLowerCase()].get()[second.toLowerCase()], insert[first.toLowerCase()].get()[second.toLowerCase()])) {
34
- return false;
35
- }
36
- }
37
- else {
38
- if ((0, compare_1.ne)(row[key.toLowerCase()], insert[key.toLowerCase()])) {
39
- return false;
40
- }
28
+ if (isSorted === true
29
+ && !(options.table instanceof types_1.HashedTable)
30
+ && options.index === undefined
31
+ && options.lines !== true) {
32
+ const insert = options.initial === true ? options.table.getRowType() : data;
33
+ if (insert !== undefined) {
34
+ const result = options.table.insertSorted(insert, (a, b) => (0, sort_1.compareRows)(a, b, tableOptions?.primaryKey?.keyFields || []), tableOptions?.primaryKey?.isUnique === true, options.noClone);
35
+ if (result.subrc === 0) {
36
+ if (options.assigning) {
37
+ options.assigning.assign(result.value);
41
38
  }
42
- }
43
- return true;
44
- };
45
- if (tableOptions.primaryKey?.isUnique === true) {
46
- const withKeyValue = [];
47
- let binary = false;
48
- const data = options?.data;
49
- if (data instanceof types_1.Structure) {
50
- const fieldName = tableOptions.primaryKey.keyFields[0].toLowerCase();
51
- if (fieldName !== "table_line" && fieldName.includes("-") === false) {
52
- withKeyValue.push({ key: (i) => { return i[fieldName]; }, value: data.get()[fieldName] });
53
- binary = true;
39
+ if (options.referenceInto) {
40
+ options.referenceInto.assign(result.value);
54
41
  }
55
42
  }
56
- else {
57
- compare = (row) => {
58
- // @ts-ignore
59
- return (0, compare_1.eq)(row.table_line, options.data);
60
- };
61
- }
62
- (0, read_table_1.readTable)(options.table, { withKey: compare, withKeyValue: withKeyValue, binarySearch: binary });
63
- if (abap.builtin.sy.get().subrc.get() === 0) {
64
- abap.builtin.sy.get().subrc.set(4);
65
- return;
66
- }
43
+ abap.builtin.sy.get().subrc.set(result.subrc);
44
+ return;
67
45
  }
68
46
  }
69
- let data = options.data;
70
- if (typeof data === "string") {
71
- const tmp = options.table.getRowType().clone();
72
- tmp.set(data);
73
- data = tmp;
74
- }
75
47
  if (data && options.index) {
76
48
  const index = options.index.get() - 1;
77
49
  const val = options.table.insertIndex(data, index);
@@ -97,6 +69,19 @@ function insertInternal(options) {
97
69
  }
98
70
  }
99
71
  else if (options.initial === true) {
72
+ if (options.table instanceof types_1.HashedTable) {
73
+ const { value: val, subrc: subrc } = options.table.insert(options.table.getRowType());
74
+ if (subrc === 0) {
75
+ if (options.assigning) {
76
+ options.assigning.assign(val);
77
+ }
78
+ if (options.referenceInto) {
79
+ options.referenceInto.assign(val);
80
+ }
81
+ }
82
+ abap.builtin.sy.get().subrc.set(subrc);
83
+ return;
84
+ }
100
85
  let index = options.table.getArrayLength();
101
86
  if (options.index) {
102
87
  index = options.index.get() - 1;
@@ -31,10 +31,10 @@ function dynamicToWhere(condition, evaluate) {
31
31
  if (evaluate === undefined) {
32
32
  throw new Error("Dynamic WHERE evaluation function is not defined");
33
33
  }
34
- const matches = text.matchAll(/([\w-]+)\s+(\w+)\s+([<>\w-]+)/gi);
34
+ const matches = text.matchAll(/([\w-]+)\s+(NOT\s+IN|\w+)\s+([<>\w-]+)/gi);
35
35
  for (const match of matches) {
36
36
  const left = match[1];
37
- const comparator = match[2].toLowerCase();
37
+ const comparator = match[2].toLowerCase().replace(/\s+/g, " ");
38
38
  let right = "";
39
39
  // console.dir({left, right});
40
40
  const cleft = "i." + left.toLowerCase().replace(/-/g, ".get().");
@@ -43,13 +43,21 @@ function dynamicToWhere(condition, evaluate) {
43
43
  const name = "fs_" + rightMatch[1].toLowerCase() + "_";
44
44
  right = `evaluate("${name}").get()["${rightMatch[2].toLowerCase()}"]`;
45
45
  }
46
+ const fieldSymbol = match[3].match(/^<(\w+)>$/);
47
+ if (right === "" && fieldSymbol) {
48
+ right = `evaluate("fs_${fieldSymbol[1].toLowerCase()}_").getPointer()`;
49
+ }
46
50
  if (right === "") {
47
- right = `evaluate("${match[3]}")`;
51
+ right = `evaluate("${match[3].toLowerCase()}")`;
48
52
  }
49
53
  if (comparator === "in") {
50
54
  const cnew = `abap.compare.in(${cleft}, ${right})`;
51
55
  text = text.replace(match[0], cnew);
52
56
  }
57
+ else if (comparator === "not in") {
58
+ const cnew = `!abap.compare.in(${cleft}, ${right})`;
59
+ text = text.replace(match[0], cnew);
60
+ }
53
61
  else {
54
62
  const cnew = `abap.compare.${comparator}(${cleft}, ${right})`;
55
63
  text = text.replace(match[0], cnew);
@@ -12,6 +12,12 @@ async function select(target, input, runtimeOptions, context) {
12
12
  target = target.getPointer();
13
13
  }
14
14
  if (rows.length === 0) {
15
+ // INTO TABLE always initializes the target, also when nothing is found;
16
+ // a work area is left untouched instead
17
+ if (runtimeOptions?.appending !== true
18
+ && (target instanceof types_1.Table || target instanceof types_1.HashedTable)) {
19
+ target.clear();
20
+ }
15
21
  abap.builtin.sy.get().dbcnt.set(0);
16
22
  abap.builtin.sy.get().subrc.set(4);
17
23
  return;
@@ -1,4 +1,4 @@
1
- import { FieldSymbol, Table } from "../types";
1
+ import { FieldSymbol, Table, TableRowType } from "../types";
2
2
  export interface ISortOptions {
3
3
  descending?: boolean;
4
4
  skipSortedCheck?: boolean;
@@ -7,4 +7,5 @@ export interface ISortOptions {
7
7
  descending?: boolean;
8
8
  }[];
9
9
  }
10
+ export declare function compareRows(a: TableRowType, b: TableRowType, keyFields: readonly string[]): number;
10
11
  export declare function sort(input: Table | FieldSymbol | any[], options?: ISortOptions): void;
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.compareRows = compareRows;
3
4
  exports.sort = sort;
4
5
  const types_1 = require("../types");
5
6
  const compare_1 = require("../compare");
@@ -63,6 +64,34 @@ function compare(a, b, input) {
63
64
  return 1;
64
65
  }
65
66
  }
67
+ function compareWholeRows(a, b) {
68
+ if ((0, compare_1.eq)(a, b)) {
69
+ return 0;
70
+ }
71
+ else if ((0, compare_1.lt)(a, b)) {
72
+ return -1;
73
+ }
74
+ else {
75
+ return 1;
76
+ }
77
+ }
78
+ function compareRows(a, b, keyFields) {
79
+ if (keyFields.length > 0) {
80
+ for (const keyField of keyFields) {
81
+ const component = keyField.toLowerCase();
82
+ const result = component === "table_line"
83
+ ? compareWholeRows(a, b)
84
+ : compare(a, b, { component });
85
+ if (result !== 0) {
86
+ return result;
87
+ }
88
+ }
89
+ return 0;
90
+ }
91
+ else {
92
+ return compareWholeRows(a, b);
93
+ }
94
+ }
66
95
  function sort(input, options) {
67
96
  // console.dir(input);
68
97
  if (input instanceof types_1.FieldSymbol) {
@@ -1,10 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Float = void 0;
4
+ const throw_error_1 = require("../throw_error");
4
5
  const hex_1 = require("./hex");
5
6
  const xstring_1 = require("./xstring");
6
7
  const integer8_1 = require("./integer8");
7
8
  const decfloat34_1 = require("./decfloat34");
9
+ const FLOAT_DIGITS = /^\s*[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)? *$/;
8
10
  /*
9
11
  function getNumberParts(x: number) {
10
12
  if(isNaN(x)) {
@@ -59,6 +61,12 @@ class Float {
59
61
  this.value = 0;
60
62
  }
61
63
  else if (typeof value === "string") {
64
+ if (value.endsWith("-")) {
65
+ value = "-" + value.substring(0, value.length - 1);
66
+ }
67
+ if (FLOAT_DIGITS.test(value) === false) {
68
+ (0, throw_error_1.throwError)("CX_SY_CONVERSION_NO_NUMBER");
69
+ }
62
70
  this.value = parseFloat(value);
63
71
  }
64
72
  else if (value instanceof integer8_1.Integer8) {
@@ -85,11 +85,11 @@ class Integer {
85
85
  this.set(Math.round(value.getRaw()));
86
86
  }
87
87
  else if (value instanceof hex_1.Hex || value instanceof xstring_1.XString || value instanceof hex_uint8_1.HexUInt8) {
88
- let num = parseInt(value.get(), 16);
89
- // handle two complement,
90
- if ((value instanceof hex_1.Hex || value instanceof hex_uint8_1.HexUInt8)
91
- && value.getLength() >= 4) {
92
- const maxVal = Math.pow(2, value.get().length / 2 * 8);
88
+ const hex = value.get();
89
+ let num = parseInt(hex, 16);
90
+ // handle two complement, the first bit is the sign
91
+ if (hex.length >= 8) {
92
+ const maxVal = Math.pow(2, hex.length / 2 * 8);
93
93
  if (num > maxVal / 2 - 1) {
94
94
  num = num - maxVal;
95
95
  }
@@ -110,6 +110,10 @@ export declare class Table implements ITable {
110
110
  getHeader(): TableRowType;
111
111
  get(): TableRowType;
112
112
  insertIndex(item: TableRowType, index: number, noClone?: boolean): any;
113
+ insertSorted(item: TableRowType, compare: (a: TableRowType, b: TableRowType) => number, unique: boolean, noClone?: boolean): {
114
+ value: TableRowType | undefined;
115
+ subrc: number;
116
+ };
113
117
  /** index = javascript indexed */
114
118
  deleteIndex(index: number): void;
115
119
  append(item: TableRowType): any;
@@ -463,6 +463,42 @@ class Table {
463
463
  }
464
464
  return val;
465
465
  }
466
+ insertSorted(item, compare, unique, noClone = false) {
467
+ if (item instanceof field_symbol_1.FieldSymbol) {
468
+ const pointer = item.getPointer();
469
+ if (pointer === undefined) {
470
+ throw new Error("insertSorted, fs not assigned");
471
+ }
472
+ return this.insertSorted(pointer, compare, unique, noClone);
473
+ }
474
+ const val = noClone === true ? item : this.cloneRow(item);
475
+ const lastIndex = this.value.length - 1;
476
+ if (lastIndex < 0) {
477
+ return { value: this.insertIndex(val, 0, true), subrc: 0 };
478
+ }
479
+ const lastComparison = compare(this.value[lastIndex], val);
480
+ if (lastComparison < 0 || (lastComparison === 0 && unique === false)) {
481
+ return { value: this.insertIndex(val, this.value.length, true), subrc: 0 };
482
+ }
483
+ else if (lastComparison === 0) {
484
+ return { value: undefined, subrc: 4 };
485
+ }
486
+ let low = 0;
487
+ let high = this.value.length;
488
+ while (low < high) {
489
+ const middle = Math.floor((low + high) / 2);
490
+ if (compare(this.value[middle], val) <= 0) {
491
+ low = middle + 1;
492
+ }
493
+ else {
494
+ high = middle;
495
+ }
496
+ }
497
+ if (unique === true && low > 0 && compare(this.value[low - 1], val) === 0) {
498
+ return { value: undefined, subrc: 4 };
499
+ }
500
+ return { value: this.insertIndex(val, low, true), subrc: 0 };
501
+ }
466
502
  /** index = javascript indexed */
467
503
  deleteIndex(index) {
468
504
  this.secondaryIndexes = {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/runtime",
3
- "version": "2.13.49",
3
+ "version": "2.13.51",
4
4
  "description": "Transpiler - Runtime",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/src/index.d.ts",
@@ -11,9 +11,9 @@
11
11
  },
12
12
  "scripts": {
13
13
  "compile": "tsc",
14
- "publish:major": "npm --no-git-tag-version version major && rm -rf build && npm install && npm run test && npm publish --access public",
15
- "publish:minor": "npm --no-git-tag-version version minor && rm -rf build && npm install && npm run test && npm publish --access public",
16
- "publish:patch": "npm --no-git-tag-version version patch && rm -rf build && npm install && npm run test && npm publish --access public",
14
+ "publish:major": "npm --no-git-tag-version version major && rimraf build && npm install && npm run test && npm publish --access public",
15
+ "publish:minor": "npm --no-git-tag-version version minor && rimraf build && npm install && npm run test && npm publish --access public",
16
+ "publish:patch": "npm --no-git-tag-version version patch && rimraf build && npm install && npm run test && npm publish --access public",
17
17
  "test": "npm run compile && mocha"
18
18
  },
19
19
  "mocha": {
@@ -33,7 +33,7 @@
33
33
  "@types/mocha": "^10.0.10",
34
34
  "@types/node": "^24.13.3",
35
35
  "chai": "^4.5.0",
36
- "mocha": "^11.7.6",
36
+ "mocha": "^11.8.0",
37
37
  "source-map-support": "^0.5.21",
38
38
  "typescript": "^6.0.3"
39
39
  },