@abaplint/runtime 2.10.81 → 2.10.83

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.
@@ -1,2 +1,2 @@
1
1
  import { FieldSymbol } from "./types";
2
- export declare function expandDynamic(code: string, ev: (name: string) => FieldSymbol | undefined): string;
2
+ export declare function expandDynamic(code: string, evaluate: (name: string) => FieldSymbol | undefined): string;
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.expandDynamic = expandDynamic;
4
4
  const expand_in_1 = require("./expand_in");
5
5
  const types_1 = require("./types");
6
- function expandDynamic(code, ev) {
6
+ function expandDynamic(code, evaluate) {
7
7
  // console.dir(code);
8
8
  if (code === "") {
9
9
  return "1 = 1";
@@ -18,7 +18,7 @@ function expandDynamic(code, ev) {
18
18
  if (match && match[1] && match[2] && match[3]) {
19
19
  let name = "fs_" + match[2] + "_";
20
20
  name = name.toLowerCase();
21
- let found = ev(name);
21
+ let found = evaluate(name);
22
22
  if (found instanceof types_1.FieldSymbol) {
23
23
  found = found.get()[match[3].toLowerCase()];
24
24
  if (found === undefined) {
@@ -38,7 +38,7 @@ function expandDynamic(code, ev) {
38
38
  if (match && match[1] && match[2]) {
39
39
  let name = "fs_" + match[1] + "_";
40
40
  name = name.toLowerCase();
41
- let found = ev(name);
41
+ let found = evaluate(name);
42
42
  if (found instanceof types_1.FieldSymbol) {
43
43
  found = found.get()[match[2].toLowerCase()];
44
44
  if (found === undefined) {
@@ -58,7 +58,7 @@ function expandDynamic(code, ev) {
58
58
  if (match && match[1]) {
59
59
  let name = "fs_" + match[1] + "_";
60
60
  name = name.toLowerCase();
61
- const found = ev(name);
61
+ const found = evaluate(name);
62
62
  if (found instanceof types_1.FieldSymbol) {
63
63
  code = code.replace(regex, " '" + found.get() + "'");
64
64
  }
@@ -50,6 +50,7 @@ import { FieldSymbol, Structure, Table } from "../types";
50
50
  import { INumeric } from "../types/_numeric";
51
51
  import { ICallFunctionOptions } from "./call_function";
52
52
  import { SelectDatabaseOptions, SelectRuntimeOptions } from "../db/db";
53
+ import { Trace } from "../trace";
53
54
  export declare class Statements {
54
55
  append: typeof append;
55
56
  assert: typeof assert;
@@ -91,11 +92,8 @@ export declare class Statements {
91
92
  receive: typeof receive;
92
93
  callTransaction: typeof callTransaction;
93
94
  private readonly context;
94
- private readonly traceTotals;
95
95
  constructor(context: Context);
96
- private _trace;
97
- private _traceAsync;
98
- _setTrace(min?: number, totals?: boolean): void;
96
+ _setTrace(min?: number, totals?: boolean): Trace;
99
97
  openCursor(target: INumeric, select: string, options: IOpenCursorDatabaseOptions): Promise<void>;
100
98
  fetchNextCursor(cursor: INumeric, target: any, packageSize?: INumeric): Promise<void>;
101
99
  closeCursor(cursor: INumeric): Promise<void>;
@@ -51,7 +51,7 @@ const call_transaction_1 = require("./call_transaction");
51
51
  const update_database_1 = require("./update_database");
52
52
  const write_1 = require("./write");
53
53
  const call_function_1 = require("./call_function");
54
- const types_1 = require("util/types");
54
+ const trace_1 = require("../trace");
55
55
  // this is a class, as statements like SELECT needs access to the database object instance
56
56
  // and WRITE will access the Console
57
57
  class Statements {
@@ -96,66 +96,9 @@ class Statements {
96
96
  this.receive = receive_1.receive;
97
97
  this.callTransaction = call_transaction_1.callTransaction;
98
98
  this.context = context;
99
- this.traceTotals = {};
100
- }
101
- _trace(func, name, min, totals) {
102
- const tt = this.traceTotals;
103
- const exec = (...options) => {
104
- const start = Date.now();
105
- const result = func.bind(this)(...options);
106
- const runtime = Date.now() - start;
107
- if (totals === true) {
108
- if (tt[name] === undefined) {
109
- tt[name] = 0;
110
- }
111
- tt[name] += runtime;
112
- }
113
- if (runtime >= min) {
114
- console.log(`STATEMENT: ${name}, ${runtime} ms`);
115
- if (totals === true) {
116
- console.log(JSON.stringify(tt));
117
- }
118
- }
119
- return result;
120
- };
121
- return exec;
122
- }
123
- _traceAsync(func, name, min, totals) {
124
- const tt = this.traceTotals;
125
- const exec = async (...options) => {
126
- const start = Date.now();
127
- const result = await func.bind(this)(...options);
128
- const runtime = Date.now() - start;
129
- if (totals === true) {
130
- if (tt[name] === undefined) {
131
- tt[name] = 0;
132
- }
133
- tt[name] += runtime;
134
- }
135
- if (runtime >= min) {
136
- console.log(`STATEMENT: ${name}, ${runtime} ms`);
137
- if (totals === true) {
138
- console.log(JSON.stringify(tt));
139
- }
140
- }
141
- return result;
142
- };
143
- return exec;
144
99
  }
145
100
  _setTrace(min = 10, totals = false) {
146
- const candidates = [...Object.keys(this), ...Object.getOwnPropertyNames(Statements.prototype)];
147
- for (const c of candidates) {
148
- if (c === "context" || c === "constructor" || c.startsWith("_") || c === "loop") {
149
- continue;
150
- }
151
- const func = this[c];
152
- if ((0, types_1.isAsyncFunction)(func)) {
153
- this[c] = this._traceAsync(func, c, min, totals);
154
- }
155
- else {
156
- this[c] = this._trace(func, c, min, totals);
157
- }
158
- }
101
+ return new trace_1.Trace().setTrace(min, totals, this);
159
102
  }
160
103
  async openCursor(target, select, options) {
161
104
  const num = await (0, open_cursor_1.openCursor)(this.context, select, options);
@@ -10,6 +10,10 @@ export interface ILoopOptions {
10
10
  from?: Integer;
11
11
  to?: Integer;
12
12
  topEquals?: topType;
13
+ dynamicWhere?: {
14
+ condition: string;
15
+ evaluate: (name: string) => FieldSymbol | undefined;
16
+ };
13
17
  }
14
18
  export declare function loop(table: Table | HashedTable | FieldSymbol | undefined, options?: ILoopOptions): AsyncGenerator<any, void, unknown>;
15
19
  export {};
@@ -23,6 +23,38 @@ function determineFromTo(array, topEquals, key) {
23
23
  to: to,
24
24
  };
25
25
  }
26
+ // todo: rewrite, this is a mess & hack & slow
27
+ function dynamicToWhere(condition, evaluate) {
28
+ // console.dir(condition);
29
+ let text = condition.replace(/ AND /gi, " && ").replace(/ OR /gi, " || ").replace(/ = /gi, " EQ ").replace(/ <> /gi, " NE ");
30
+ // console.dir(text);
31
+ let regex = /([\w-]+)\s+(\w+)\s+([<>\w-]+)/gi;
32
+ let matches = text.matchAll(regex);
33
+ for (const match of matches) {
34
+ const left = match[1];
35
+ const comparator = match[2].toLowerCase();
36
+ const right = match[3];
37
+ // console.dir({left, right});
38
+ const cleft = "i." + left.toLowerCase().replace(/-/g, ".get().");
39
+ const cright = right;
40
+ const cnew = `abap.compare.${comparator}(${cleft}, ${cright})`;
41
+ text = text.replace(match[0], cnew);
42
+ }
43
+ regex = / <(\w+)>-(\w+)/gi;
44
+ matches = text.matchAll(regex);
45
+ for (const match of matches) {
46
+ const name = "fs_" + match[1].toLowerCase() + "_";
47
+ const value = evaluate(name)?.get()?.[match[2].toLowerCase()]?.get();
48
+ text = text.replace(match[0], " '" + value + "'");
49
+ }
50
+ // console.dir(text);
51
+ // @ts-ignore
52
+ return async (i) => {
53
+ // console.dir(i);
54
+ // eslint-disable-next-line no-eval
55
+ return eval(text);
56
+ };
57
+ }
26
58
  async function* loop(table, options) {
27
59
  if (table === undefined) {
28
60
  throw new Error("LOOP at undefined");
@@ -35,6 +67,14 @@ async function* loop(table, options) {
35
67
  yield* loop(pnt, options);
36
68
  return;
37
69
  }
70
+ if (options?.dynamicWhere) {
71
+ const dynamicWhere = options.dynamicWhere;
72
+ const newOptions = { ...options };
73
+ delete newOptions.dynamicWhere;
74
+ newOptions.where = dynamicToWhere(dynamicWhere.condition, dynamicWhere.evaluate);
75
+ yield* loop(table, newOptions);
76
+ return;
77
+ }
38
78
  const length = table.getArrayLength();
39
79
  if (length === 0) {
40
80
  // @ts-ignore
@@ -0,0 +1,12 @@
1
+ export declare class Trace {
2
+ private readonly traceTotals;
3
+ setTrace(min: number, totals: boolean, statements: any): this;
4
+ getTotals(): {
5
+ [name: string]: {
6
+ calls: number;
7
+ totalRuntime: number;
8
+ };
9
+ };
10
+ private _trace;
11
+ private _traceAsync;
12
+ }
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Trace = void 0;
4
+ const types_1 = require("util/types");
5
+ const statements_1 = require("./statements");
6
+ class Trace {
7
+ constructor() {
8
+ this.traceTotals = {};
9
+ }
10
+ setTrace(min, totals, statements) {
11
+ const candidates = [...Object.keys(statements), ...Object.getOwnPropertyNames(statements_1.Statements.prototype)];
12
+ for (const c of candidates) {
13
+ if (c === "context" || c === "constructor" || c.startsWith("_") || c === "loop") {
14
+ continue;
15
+ }
16
+ const func = statements[c];
17
+ if ((0, types_1.isAsyncFunction)(func)) {
18
+ statements[c] = this._traceAsync(func, c, min, totals);
19
+ }
20
+ else {
21
+ statements[c] = this._trace(func, c, min, totals);
22
+ }
23
+ }
24
+ return this;
25
+ }
26
+ getTotals() {
27
+ return this.traceTotals;
28
+ }
29
+ //////////////////////////////////////////
30
+ _trace(func, name, min, totals) {
31
+ const tt = this.traceTotals;
32
+ const exec1 = (...options) => {
33
+ const start = Date.now();
34
+ const result = func.bind(this)(...options);
35
+ const runtime = Date.now() - start;
36
+ if (totals === true) {
37
+ if (tt[name] === undefined) {
38
+ tt[name] = { calls: 0, totalRuntime: 0 };
39
+ }
40
+ tt[name].totalRuntime += runtime;
41
+ tt[name].calls++;
42
+ }
43
+ if (min > 0 && runtime >= min) {
44
+ console.log(`STATEMENT: ${name}, ${runtime} ms`);
45
+ if (totals === true) {
46
+ console.log(JSON.stringify(tt));
47
+ }
48
+ }
49
+ return result;
50
+ };
51
+ return exec1;
52
+ }
53
+ _traceAsync(func, name, min, totals) {
54
+ const tt = this.traceTotals;
55
+ const exec2 = async (...options) => {
56
+ const start = Date.now();
57
+ const result = await func.bind(this)(...options);
58
+ const runtime = Date.now() - start;
59
+ if (totals === true) {
60
+ if (tt[name] === undefined) {
61
+ tt[name] = { calls: 0, totalRuntime: 0 };
62
+ }
63
+ tt[name].totalRuntime += runtime;
64
+ tt[name].calls++;
65
+ }
66
+ if (min > 0 && runtime >= min) {
67
+ console.log(`STATEMENT: ${name}, ${runtime} ms`);
68
+ if (totals === true) {
69
+ console.log(JSON.stringify(tt));
70
+ }
71
+ }
72
+ return result;
73
+ };
74
+ return exec2;
75
+ }
76
+ }
77
+ exports.Trace = Trace;
78
+ //# sourceMappingURL=trace.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/runtime",
3
- "version": "2.10.81",
3
+ "version": "2.10.83",
4
4
  "description": "Transpiler - Runtime",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/src/index.d.ts",