@jbrowse/jexl 2.3.1 → 3.0.1
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/CHANGELOG.md +27 -0
- package/LICENSE.txt +1 -0
- package/README.md +76 -74
- package/dist/Expression.d.ts +2 -12
- package/dist/Expression.js +5 -27
- package/dist/Expression.js.map +1 -1
- package/dist/Jexl.d.ts +6 -40
- package/dist/Jexl.js +7 -49
- package/dist/Jexl.js.map +1 -1
- package/dist/evaluator/Evaluator.d.ts +14 -55
- package/dist/evaluator/Evaluator.js +14 -73
- package/dist/evaluator/Evaluator.js.map +1 -1
- package/dist/evaluator/handlers.d.ts +19 -18
- package/dist/evaluator/handlers.js +54 -62
- package/dist/evaluator/handlers.js.map +1 -1
- package/dist/grammar.d.ts +3 -4
- package/dist/grammar.js +16 -39
- package/dist/grammar.js.map +1 -1
- package/esm/Expression.d.ts +2 -12
- package/esm/Expression.js +5 -27
- package/esm/Expression.js.map +1 -1
- package/esm/Jexl.d.ts +6 -40
- package/esm/Jexl.js +7 -49
- package/esm/Jexl.js.map +1 -1
- package/esm/evaluator/Evaluator.d.ts +14 -55
- package/esm/evaluator/Evaluator.js +14 -73
- package/esm/evaluator/Evaluator.js.map +1 -1
- package/esm/evaluator/handlers.d.ts +19 -18
- package/esm/evaluator/handlers.js +54 -62
- package/esm/evaluator/handlers.js.map +1 -1
- package/esm/grammar.d.ts +3 -4
- package/esm/grammar.js +16 -39
- package/esm/grammar.js.map +1 -1
- package/package.json +2 -1
- package/src/Expression.ts +5 -36
- package/src/Jexl.ts +7 -54
- package/src/evaluator/Evaluator.ts +14 -92
- package/src/evaluator/handlers.ts +54 -68
- package/src/grammar.ts +17 -38
- package/src/types.ts +4 -1
- package/dist/PromiseSync.d.ts +0 -13
- package/dist/PromiseSync.js +0 -80
- package/dist/PromiseSync.js.map +0 -1
- package/esm/PromiseSync.d.ts +0 -13
- package/esm/PromiseSync.js +0 -78
- package/esm/PromiseSync.js.map +0 -1
- package/src/PromiseSync.ts +0 -86
|
@@ -3,15 +3,14 @@
|
|
|
3
3
|
* Copyright 2020 Tom Shawver
|
|
4
4
|
*/
|
|
5
5
|
const poolNames = {
|
|
6
|
-
functions: 'Jexl Function'
|
|
7
|
-
transforms: 'Transform'
|
|
6
|
+
functions: 'Jexl Function'
|
|
8
7
|
};
|
|
9
8
|
/**
|
|
10
9
|
* Evaluates an ArrayLiteral by returning its value, with each element
|
|
11
10
|
* independently run through the evaluator.
|
|
12
11
|
* @param {{type: 'ObjectLiteral', value: <{}>}} ast An expression tree with an
|
|
13
12
|
* ObjectLiteral as the top node
|
|
14
|
-
* @returns {
|
|
13
|
+
* @returns {[]} an array of evaluated values.
|
|
15
14
|
* @private
|
|
16
15
|
*/
|
|
17
16
|
export function ArrayLiteral(ast) {
|
|
@@ -23,12 +22,12 @@ export function ArrayLiteral(ast) {
|
|
|
23
22
|
* evaluators: `eval` is called with the left and right operands pre-evaluated.
|
|
24
23
|
* `evalOnDemand`, if it exists, will be called with the left and right operands
|
|
25
24
|
* each individually wrapped in an object with an "eval" function that returns
|
|
26
|
-
*
|
|
27
|
-
*
|
|
25
|
+
* the resulting value. This allows the binary expression to evaluate the
|
|
26
|
+
* operands conditionally.
|
|
28
27
|
* @param {{type: 'BinaryExpression', operator: <string>, left: {},
|
|
29
28
|
* right: {}}} ast An expression tree with a BinaryExpression as the top
|
|
30
29
|
* node
|
|
31
|
-
* @returns {
|
|
30
|
+
* @returns {*} the value of the BinaryExpression.
|
|
32
31
|
* @private
|
|
33
32
|
*/
|
|
34
33
|
export function BinaryExpression(ast) {
|
|
@@ -37,44 +36,43 @@ export function BinaryExpression(ast) {
|
|
|
37
36
|
const wrap = (subAst) => ({ eval: () => this.eval(subAst) });
|
|
38
37
|
return grammarOp.evalOnDemand(wrap(ast.left), wrap(ast.right));
|
|
39
38
|
}
|
|
40
|
-
|
|
39
|
+
const left = this.eval(ast.left);
|
|
40
|
+
const right = this.eval(ast.right);
|
|
41
|
+
return grammarOp.eval(left, right);
|
|
41
42
|
}
|
|
42
43
|
/**
|
|
43
44
|
* Evaluates a ConditionalExpression node by first evaluating its test branch,
|
|
44
|
-
* and
|
|
45
|
-
*
|
|
46
|
-
*
|
|
45
|
+
* and returning the consequent branch if the test is truthy, or the alternate
|
|
46
|
+
* branch if it is not. If there is no consequent branch, the test result will
|
|
47
|
+
* be used instead.
|
|
47
48
|
* @param {{type: 'ConditionalExpression', test: {}, consequent: {},
|
|
48
49
|
* alternate: {}}} ast An expression tree with a ConditionalExpression as
|
|
49
50
|
* the top node
|
|
50
51
|
* @private
|
|
51
52
|
*/
|
|
52
53
|
export function ConditionalExpression(ast) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return res;
|
|
59
|
-
}
|
|
60
|
-
return this.eval(ast.alternate);
|
|
61
|
-
});
|
|
54
|
+
const res = this.eval(ast.test);
|
|
55
|
+
if (res) {
|
|
56
|
+
return ast.consequent ? this.eval(ast.consequent) : res;
|
|
57
|
+
}
|
|
58
|
+
return this.eval(ast.alternate);
|
|
62
59
|
}
|
|
63
60
|
/**
|
|
64
|
-
* Evaluates a FilterExpression by applying
|
|
61
|
+
* Evaluates a FilterExpression by applying bracket notation for array/object access.
|
|
62
|
+
* Note: Relative filtering (with leading dot) is not supported.
|
|
65
63
|
* @param {{type: 'FilterExpression', relative: <boolean>, expr: {},
|
|
66
64
|
* subject: {}}} ast An expression tree with a FilterExpression as the top
|
|
67
65
|
* node
|
|
68
|
-
* @returns {
|
|
66
|
+
* @returns {*} the value at the specified index/property.
|
|
69
67
|
* @private
|
|
70
68
|
*/
|
|
71
69
|
export function FilterExpression(ast) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
70
|
+
const subject = this.eval(ast.subject);
|
|
71
|
+
if (ast.relative) {
|
|
72
|
+
throw new Error('Relative filter expressions are not supported');
|
|
73
|
+
}
|
|
74
|
+
const index = this.eval(ast.expr);
|
|
75
|
+
return subject?.[index];
|
|
78
76
|
}
|
|
79
77
|
/**
|
|
80
78
|
* Evaluates an Identifier by either stemming from the evaluated 'from'
|
|
@@ -82,8 +80,7 @@ export function FilterExpression(ast) {
|
|
|
82
80
|
* constructed.
|
|
83
81
|
* @param {{type: 'Identifier', value: <string>, [from]: {}}} ast An expression
|
|
84
82
|
* tree with an Identifier as the top node
|
|
85
|
-
* @returns {
|
|
86
|
-
* will resolve with the identifier's value.
|
|
83
|
+
* @returns {*} the identifier's value.
|
|
87
84
|
* @private
|
|
88
85
|
*/
|
|
89
86
|
export function Identifier(ast) {
|
|
@@ -91,13 +88,12 @@ export function Identifier(ast) {
|
|
|
91
88
|
const contextSource = ast.relative ? this._relContext : this._context;
|
|
92
89
|
return contextSource[ast.value];
|
|
93
90
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
});
|
|
91
|
+
const context = this.eval(ast.from);
|
|
92
|
+
if (context == null) {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
const ctx = Array.isArray(context) ? context[0] : context;
|
|
96
|
+
return ctx?.[ast.value];
|
|
101
97
|
}
|
|
102
98
|
/**
|
|
103
99
|
* Evaluates a Literal by returning its value property.
|
|
@@ -114,29 +110,28 @@ export function Literal(ast) {
|
|
|
114
110
|
* and concatenating all parts into a final string.
|
|
115
111
|
* @param {{type: 'TemplateLiteral', parts: Array<{}>}} ast An expression
|
|
116
112
|
* tree with a TemplateLiteral as the top node
|
|
117
|
-
* @returns {
|
|
113
|
+
* @returns {string} the final interpolated string
|
|
118
114
|
* @private
|
|
119
115
|
*/
|
|
120
116
|
export function TemplateLiteral(ast) {
|
|
121
|
-
const
|
|
117
|
+
const values = ast.parts.map((part) => {
|
|
122
118
|
if (part.type === 'static') {
|
|
123
|
-
return
|
|
119
|
+
return part.value;
|
|
124
120
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
});
|
|
121
|
+
const result = this.eval(part.value);
|
|
122
|
+
if (result == null) {
|
|
123
|
+
return '';
|
|
124
|
+
}
|
|
125
|
+
return String(result);
|
|
131
126
|
});
|
|
132
|
-
return
|
|
127
|
+
return values.join('');
|
|
133
128
|
}
|
|
134
129
|
/**
|
|
135
130
|
* Evaluates an ObjectLiteral by returning its value, with each key
|
|
136
131
|
* independently run through the evaluator.
|
|
137
132
|
* @param {{type: 'ObjectLiteral', value: <{}>}} ast An expression tree with an
|
|
138
133
|
* ObjectLiteral as the top node
|
|
139
|
-
* @returns {
|
|
134
|
+
* @returns {{}} a map of evaluated values.
|
|
140
135
|
* @private
|
|
141
136
|
*/
|
|
142
137
|
export function ObjectLiteral(ast) {
|
|
@@ -147,8 +142,7 @@ export function ObjectLiteral(ast) {
|
|
|
147
142
|
* function defined in one of the grammar's function pools.
|
|
148
143
|
* @param {{type: 'FunctionCall', name: <string>}} ast An
|
|
149
144
|
* expression tree with a FunctionCall as the top node
|
|
150
|
-
* @returns {
|
|
151
|
-
* will resolve with the resulting value.
|
|
145
|
+
* @returns {*} the value of the function call.
|
|
152
146
|
* @private
|
|
153
147
|
*/
|
|
154
148
|
export function FunctionCall(ast) {
|
|
@@ -161,18 +155,20 @@ export function FunctionCall(ast) {
|
|
|
161
155
|
if (!func) {
|
|
162
156
|
throw new Error(`${poolName} ${ast.name} is not defined.`);
|
|
163
157
|
}
|
|
164
|
-
|
|
158
|
+
const args = this.evalArray(ast.args || []);
|
|
159
|
+
return func(...args);
|
|
165
160
|
}
|
|
166
161
|
/**
|
|
167
162
|
* Evaluates a Unary expression by passing the right side through the
|
|
168
163
|
* operator's eval function.
|
|
169
164
|
* @param {{type: 'UnaryExpression', operator: <string>, right: {}}} ast An
|
|
170
165
|
* expression tree with a UnaryExpression as the top node
|
|
171
|
-
* @returns {
|
|
166
|
+
* @returns {*} the value of the UnaryExpression.
|
|
172
167
|
* @constructor
|
|
173
168
|
*/
|
|
174
169
|
export function UnaryExpression(ast) {
|
|
175
|
-
|
|
170
|
+
const right = this.eval(ast.right);
|
|
171
|
+
return this._grammar.elements[ast.operator].eval(right);
|
|
176
172
|
}
|
|
177
173
|
/**
|
|
178
174
|
* Evaluates a SequenceExpression by evaluating each expression in order
|
|
@@ -180,23 +176,19 @@ export function UnaryExpression(ast) {
|
|
|
180
176
|
*/
|
|
181
177
|
export function SequenceExpression(ast) {
|
|
182
178
|
let lastValue;
|
|
183
|
-
let promise = this.Promise.resolve();
|
|
184
179
|
for (const expr of ast.expressions) {
|
|
185
|
-
|
|
186
|
-
lastValue = val;
|
|
187
|
-
}));
|
|
180
|
+
lastValue = this.eval(expr);
|
|
188
181
|
}
|
|
189
|
-
return
|
|
182
|
+
return lastValue;
|
|
190
183
|
}
|
|
191
184
|
/**
|
|
192
185
|
* Evaluates an AssignmentExpression by evaluating the right side
|
|
193
186
|
* and assigning it to the variable name on the left side.
|
|
194
187
|
*/
|
|
195
188
|
export function AssignmentExpression(ast) {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
});
|
|
189
|
+
const value = this.eval(ast.right);
|
|
190
|
+
const varName = ast.left.value;
|
|
191
|
+
this._context[varName] = value;
|
|
192
|
+
return value;
|
|
201
193
|
}
|
|
202
194
|
//# sourceMappingURL=handlers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/evaluator/handlers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,MAAM,SAAS,GAA2B;IACxC,SAAS,EAAE,eAAe;
|
|
1
|
+
{"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/evaluator/handlers.ts"],"names":[],"mappings":"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"}
|
package/esm/grammar.d.ts
CHANGED
|
@@ -3,10 +3,10 @@ export interface BinaryOp {
|
|
|
3
3
|
precedence: number;
|
|
4
4
|
eval?: (left: any, right: any) => any;
|
|
5
5
|
evalOnDemand?: (left: {
|
|
6
|
-
eval: () =>
|
|
6
|
+
eval: () => any;
|
|
7
7
|
}, right: {
|
|
8
|
-
eval: () =>
|
|
9
|
-
}) =>
|
|
8
|
+
eval: () => any;
|
|
9
|
+
}) => any;
|
|
10
10
|
}
|
|
11
11
|
export interface UnaryOp {
|
|
12
12
|
type: 'unaryOp';
|
|
@@ -20,6 +20,5 @@ export type GrammarElement = BinaryOp | UnaryOp | SimpleElement;
|
|
|
20
20
|
export interface Grammar {
|
|
21
21
|
elements: Record<string, GrammarElement>;
|
|
22
22
|
functions: Record<string, (...args: any[]) => any>;
|
|
23
|
-
transforms: Record<string, (val: any, ...args: any[]) => any>;
|
|
24
23
|
}
|
|
25
24
|
export declare const getGrammar: () => Grammar;
|
package/esm/grammar.js
CHANGED
|
@@ -12,7 +12,6 @@ export const getGrammar = () => ({
|
|
|
12
12
|
'.': { type: 'dot' },
|
|
13
13
|
'[': { type: 'openBracket' },
|
|
14
14
|
']': { type: 'closeBracket' },
|
|
15
|
-
'|': { type: 'pipe' },
|
|
16
15
|
'{': { type: 'openCurl' },
|
|
17
16
|
'}': { type: 'closeCurl' },
|
|
18
17
|
':': { type: 'colon' },
|
|
@@ -90,24 +89,22 @@ export const getGrammar = () => ({
|
|
|
90
89
|
type: 'binaryOp',
|
|
91
90
|
precedence: 10,
|
|
92
91
|
evalOnDemand: (left, right) => {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
});
|
|
92
|
+
const leftVal = left.eval();
|
|
93
|
+
if (!leftVal) {
|
|
94
|
+
return leftVal;
|
|
95
|
+
}
|
|
96
|
+
return right.eval();
|
|
99
97
|
}
|
|
100
98
|
},
|
|
101
99
|
'||': {
|
|
102
100
|
type: 'binaryOp',
|
|
103
101
|
precedence: 10,
|
|
104
102
|
evalOnDemand: (left, right) => {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
});
|
|
103
|
+
const leftVal = left.eval();
|
|
104
|
+
if (leftVal) {
|
|
105
|
+
return leftVal;
|
|
106
|
+
}
|
|
107
|
+
return right.eval();
|
|
111
108
|
}
|
|
112
109
|
},
|
|
113
110
|
in: {
|
|
@@ -144,32 +141,12 @@ export const getGrammar = () => ({
|
|
|
144
141
|
* All of these are pre-evaluated to their actual values before calling
|
|
145
142
|
* the function.
|
|
146
143
|
*
|
|
147
|
-
* The Jexl function should return
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
* appropriate when the function would normally return a value, but
|
|
153
|
-
* cannot due to some other failure.
|
|
154
|
-
*/
|
|
155
|
-
functions: {},
|
|
156
|
-
/**
|
|
157
|
-
* A map of transform names to transform functions. A transform function
|
|
158
|
-
* takes one ore more arguemnts:
|
|
159
|
-
*
|
|
160
|
-
* - {*} val: A value to be transformed
|
|
161
|
-
* - {*} ...args: A variable number of arguments passed to this transform.
|
|
162
|
-
* All of these are pre-evaluated to their actual values before calling
|
|
163
|
-
* the function.
|
|
164
|
-
*
|
|
165
|
-
* The transform function should return either the transformed value, or
|
|
166
|
-
* a Promises/A+ Promise object that resolves with the value and rejects
|
|
167
|
-
* or throws only when an unrecoverable error occurs. Transforms should
|
|
168
|
-
* generally return undefined when they don't make sense to be used on the
|
|
169
|
-
* given value type, rather than throw/reject. An error is only
|
|
170
|
-
* appropriate when the transform would normally return a value, but
|
|
171
|
-
* cannot due to some other failure.
|
|
144
|
+
* The Jexl function should return the resulting value, or throw when an
|
|
145
|
+
* unrecoverable error occurs. Functions should generally return undefined
|
|
146
|
+
* when they don't make sense to be used on the given value type, rather
|
|
147
|
+
* than throw. An error is only appropriate when the function would normally
|
|
148
|
+
* return a value, but cannot due to some other failure.
|
|
172
149
|
*/
|
|
173
|
-
|
|
150
|
+
functions: {}
|
|
174
151
|
});
|
|
175
152
|
//# sourceMappingURL=grammar.js.map
|
package/esm/grammar.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grammar.js","sourceRoot":"","sources":["../src/grammar.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"grammar.js","sourceRoot":"","sources":["../src/grammar.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA4BH,MAAM,CAAC,MAAM,UAAU,GAAG,GAAY,EAAE,CAAC,CAAC;IACxC;;;;OAIG;IACH,QAAQ,EAAE;QACR,GAAG,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;QACpB,GAAG,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE;QAC5B,GAAG,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE;QAC7B,GAAG,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;QACzB,GAAG,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;QAC1B,GAAG,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;QACtB,GAAG,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;QACtB,GAAG,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;QAC1B,GAAG,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE;QAC3B,GAAG,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;QACzB,GAAG,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;QAC1B,GAAG,EAAE;YACH,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,EAAE;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,GAAG,KAAK;SACpC;QACD,GAAG,EAAE;YACH,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,EAAE;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,GAAG,KAAK;SACpC;QACD,GAAG,EAAE;YACH,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,EAAE;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,GAAG,KAAK;SACpC;QACD,GAAG,EAAE;YACH,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,EAAE;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,GAAG,KAAK;SACpC;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,EAAE;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC;SAChD;QACD,GAAG,EAAE;YACH,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,EAAE;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,GAAG,KAAK;SACpC;QACD,GAAG,EAAE;YACH,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,EAAE;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC;SAC7C;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,EAAE;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,IAAI,KAAK;SACrC;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,EAAE;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,IAAI,KAAK;SACrC;QACD,GAAG,EAAE;YACH,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,EAAE;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,GAAG,KAAK;SACpC;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,EAAE;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,IAAI,KAAK;SACrC;QACD,GAAG,EAAE;YACH,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,EAAE;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,GAAG,KAAK;SACpC;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,EAAE;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,IAAI,KAAK;SACrC;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,EAAE;YACd,YAAY,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;gBAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;gBAC3B,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,OAAO,OAAO,CAAA;gBAChB,CAAC;gBACD,OAAO,KAAK,CAAC,IAAI,EAAE,CAAA;YACrB,CAAC;SACF;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,EAAE;YACd,YAAY,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;gBAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;gBAC3B,IAAI,OAAO,EAAE,CAAC;oBACZ,OAAO,OAAO,CAAA;gBAChB,CAAC;gBACD,OAAO,KAAK,CAAC,IAAI,EAAE,CAAA;YACrB,CAAC;SACF;QACD,EAAE,EAAE;YACF,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,EAAE;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;gBACpB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;oBAC9B,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;gBAC7B,CAAC;gBACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzB,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;gBAC7B,CAAC;gBACD,OAAO,KAAK,CAAA;YACd,CAAC;SACF;QACD,GAAG,EAAE;YACH,IAAI,EAAE,SAAS;YACf,UAAU,EAAE,QAAQ;YACpB,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK;SACxB;QACD,GAAG,EAAE;YACH,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,CAAC;YACb,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;gBACtB,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAA;YACjD,CAAC;SACF;KACF;IAED;;;;;;;;;;;;;OAaG;IACH,SAAS,EAAE,EAAE;CACd,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/jexl",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "A fork of the jexl lang for jbrowse",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
"homepage": "https://github.com/TomFrost/jexl",
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@types/node": "^25.0.3",
|
|
55
|
+
"@vitest/coverage-v8": "^4.0.16",
|
|
55
56
|
"eslint": "^9.39.2",
|
|
56
57
|
"eslint-plugin-import": "^2.32.0",
|
|
57
58
|
"eslint-plugin-unicorn": "^62.0.0",
|
package/src/Expression.ts
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import Lexer from './Lexer.ts'
|
|
7
|
-
import PromiseSync from './PromiseSync.ts'
|
|
8
7
|
import Evaluator from './evaluator/Evaluator.ts'
|
|
9
8
|
import Parser from './parser/Parser.ts'
|
|
10
9
|
|
|
@@ -15,8 +14,6 @@ interface Grammar {
|
|
|
15
14
|
[key: string]: any
|
|
16
15
|
}
|
|
17
16
|
|
|
18
|
-
type PromiseConstructor = typeof Promise | typeof PromiseSync
|
|
19
|
-
|
|
20
17
|
class Expression {
|
|
21
18
|
_grammar: Grammar
|
|
22
19
|
_exprStr: string
|
|
@@ -44,44 +41,16 @@ class Expression {
|
|
|
44
41
|
}
|
|
45
42
|
|
|
46
43
|
/**
|
|
47
|
-
*
|
|
48
|
-
* @param {Object} [context] A mapping of variables to values, which will be
|
|
49
|
-
* made accessible to the Jexl expression when evaluating it
|
|
50
|
-
* @returns {Promise<*>} resolves with the result of the evaluation.
|
|
51
|
-
*/
|
|
52
|
-
eval(context = {}) {
|
|
53
|
-
return this._eval(context, Promise)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Synchronously evaluates the expression within an optional context.
|
|
44
|
+
* Evaluates the expression within an optional context.
|
|
58
45
|
* @param {Object} [context] A mapping of variables to values, which will be
|
|
59
46
|
* made accessible to the Jexl expression when evaluating it
|
|
60
47
|
* @returns {*} the result of the evaluation.
|
|
61
48
|
* @throws {*} on error
|
|
62
49
|
*/
|
|
63
|
-
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
throw res.error
|
|
68
|
-
}
|
|
69
|
-
throw new Error(typeof res.error === 'string' ? res.error : JSON.stringify(res.error))
|
|
70
|
-
}
|
|
71
|
-
return res.value
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
_eval(context: any, promise: PromiseConstructor) {
|
|
75
|
-
return promise.resolve().then(() => {
|
|
76
|
-
const ast = this._getAst()
|
|
77
|
-
const evaluator = new Evaluator(
|
|
78
|
-
this._grammar,
|
|
79
|
-
context,
|
|
80
|
-
undefined,
|
|
81
|
-
promise
|
|
82
|
-
)
|
|
83
|
-
return evaluator.eval(ast!)
|
|
84
|
-
})
|
|
50
|
+
eval(context = {}) {
|
|
51
|
+
const ast = this._getAst()
|
|
52
|
+
const evaluator = new Evaluator(this._grammar, context)
|
|
53
|
+
return evaluator.eval(ast!)
|
|
85
54
|
}
|
|
86
55
|
|
|
87
56
|
_getAst() {
|
package/src/Jexl.ts
CHANGED
|
@@ -9,7 +9,6 @@ import { getGrammar } from './grammar.ts'
|
|
|
9
9
|
interface Grammar {
|
|
10
10
|
elements: Record<string, any>
|
|
11
11
|
functions: Record<string, (...args: any[]) => any>
|
|
12
|
-
transforms: Record<string, (val: any, ...args: any[]) => any>
|
|
13
12
|
}
|
|
14
13
|
|
|
15
14
|
/**
|
|
@@ -39,13 +38,11 @@ class Jexl {
|
|
|
39
38
|
* @param {number} precedence The operator's precedence
|
|
40
39
|
* @param {function} fn A function to run to calculate the result. The function
|
|
41
40
|
* will be called with two arguments: left and right, denoting the values
|
|
42
|
-
* on either side of the operator. It should return
|
|
43
|
-
* value, or a Promise that resolves with the resulting value.
|
|
41
|
+
* on either side of the operator. It should return the resulting value.
|
|
44
42
|
* @param {boolean} [manualEval] If true, the `left` and `right` arguments
|
|
45
43
|
* will be wrapped in objects with an `eval` function. Calling
|
|
46
|
-
* left.eval() or right.eval() will return
|
|
47
|
-
*
|
|
48
|
-
* operands.
|
|
44
|
+
* left.eval() or right.eval() will return that operand's actual value.
|
|
45
|
+
* This is useful to conditionally evaluate operands.
|
|
49
46
|
*/
|
|
50
47
|
addBinaryOp(
|
|
51
48
|
operator: string,
|
|
@@ -88,8 +85,7 @@ class Jexl {
|
|
|
88
85
|
* @param {string} operator The operator string to be added
|
|
89
86
|
* @param {function} fn A function to run to calculate the result. The function
|
|
90
87
|
* will be called with one argument: the literal value to the right of the
|
|
91
|
-
* operator. It should return
|
|
92
|
-
* that resolves with the resulting value.
|
|
88
|
+
* operator. It should return the resulting value.
|
|
93
89
|
*/
|
|
94
90
|
addUnaryOp(operator: string, fn: (right: any) => any) {
|
|
95
91
|
this._addGrammarElement(operator, {
|
|
@@ -99,28 +95,6 @@ class Jexl {
|
|
|
99
95
|
})
|
|
100
96
|
}
|
|
101
97
|
|
|
102
|
-
/**
|
|
103
|
-
* Adds or replaces a transform function in this Jexl instance.
|
|
104
|
-
* @param {string} name The name of the transform function, as it will be used
|
|
105
|
-
* within Jexl expressions
|
|
106
|
-
* @param {function} fn The function to be executed when this transform is
|
|
107
|
-
* invoked. It will be provided with at least one argument:
|
|
108
|
-
* - {*} value: The value to be transformed
|
|
109
|
-
* - {...*} args: The arguments for this transform
|
|
110
|
-
*/
|
|
111
|
-
addTransform(name: string, fn: (val: any, ...args: any[]) => any) {
|
|
112
|
-
this._grammar.transforms[name] = fn
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Syntactic sugar for calling {@link #addTransform} repeatedly. This function
|
|
117
|
-
* accepts a map of one or more transform names to their transform function.
|
|
118
|
-
* @param {{}} map A map of transform names to transform functions
|
|
119
|
-
*/
|
|
120
|
-
addTransforms(map: Record<string, (val: any, ...args: any[]) => any>) {
|
|
121
|
-
Object.assign(this._grammar.transforms, map)
|
|
122
|
-
}
|
|
123
|
-
|
|
124
98
|
/**
|
|
125
99
|
* Creates an Expression object from the given Jexl expression string, and
|
|
126
100
|
* immediately compiles it. The returned Expression object can then be
|
|
@@ -154,37 +128,16 @@ class Jexl {
|
|
|
154
128
|
}
|
|
155
129
|
|
|
156
130
|
/**
|
|
157
|
-
*
|
|
158
|
-
* @param {string} name The name of the transform function
|
|
159
|
-
* @returns {function} The transform function
|
|
160
|
-
*/
|
|
161
|
-
getTransform(name: string) {
|
|
162
|
-
return this._grammar.transforms[name]
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Asynchronously evaluates a Jexl string within an optional context.
|
|
167
|
-
* @param {string} expression The Jexl expression to be evaluated
|
|
168
|
-
* @param {Object} [context] A mapping of variables to values, which will be
|
|
169
|
-
* made accessible to the Jexl expression when evaluating it
|
|
170
|
-
* @returns {Promise<*>} resolves with the result of the evaluation.
|
|
171
|
-
*/
|
|
172
|
-
eval(expression: string, context = {}) {
|
|
173
|
-
const exprObj = this.createExpression(expression)
|
|
174
|
-
return exprObj.eval(context)
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Synchronously evaluates a Jexl string within an optional context.
|
|
131
|
+
* Evaluates a Jexl string within an optional context.
|
|
179
132
|
* @param {string} expression The Jexl expression to be evaluated
|
|
180
133
|
* @param {Object} [context] A mapping of variables to values, which will be
|
|
181
134
|
* made accessible to the Jexl expression when evaluating it
|
|
182
135
|
* @returns {*} the result of the evaluation.
|
|
183
136
|
* @throws {*} on error
|
|
184
137
|
*/
|
|
185
|
-
|
|
138
|
+
eval(expression: string, context = {}) {
|
|
186
139
|
const exprObj = this.createExpression(expression)
|
|
187
|
-
return exprObj.
|
|
140
|
+
return exprObj.eval(context)
|
|
188
141
|
}
|
|
189
142
|
|
|
190
143
|
/**
|