@cloudpss/expression 0.6.0-alpha.8 → 0.6.0-beta.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/dist/analyze.d.ts +6 -3
- package/dist/analyze.d.ts.map +1 -1
- package/dist/analyze.js +13 -33
- package/dist/analyze.js.map +1 -1
- package/dist/definitions/argument.d.ts +3 -11
- package/dist/definitions/argument.d.ts.map +1 -1
- package/dist/definitions/constraint.d.ts +2 -2
- package/dist/definitions/constraint.d.ts.map +1 -1
- package/dist/definitions/constraint.js +1 -1
- package/dist/definitions/constraint.js.map +1 -1
- package/dist/definitions/parameter-group.js +4 -4
- package/dist/definitions/parameter-group.js.map +1 -1
- package/dist/definitions/parameter.d.ts +22 -14
- package/dist/definitions/parameter.d.ts.map +1 -1
- package/dist/definitions/parameter.js +10 -1
- package/dist/definitions/parameter.js.map +1 -1
- package/dist/definitions/utils.d.ts +28 -0
- package/dist/definitions/utils.d.ts.map +1 -0
- package/dist/definitions/utils.js +272 -0
- package/dist/definitions/utils.js.map +1 -0
- package/dist/definitions/variable.js +1 -1
- package/dist/definitions/variable.js.map +1 -1
- package/dist/definitions.d.ts +1 -2
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js +1 -1
- package/dist/definitions.js.map +1 -1
- package/dist/eval.d.ts +3 -5
- package/dist/eval.d.ts.map +1 -1
- package/dist/eval.js +12 -20
- package/dist/eval.js.map +1 -1
- package/dist/expression.d.ts +10 -4
- package/dist/expression.d.ts.map +1 -1
- package/dist/expression.js +6 -6
- package/dist/expression.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/interface.d.ts +30 -0
- package/dist/interface.d.ts.map +1 -0
- package/dist/interface.js +6 -0
- package/dist/interface.js.map +1 -0
- package/dist/main.d.ts +41 -28
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +165 -149
- package/dist/main.js.map +1 -1
- package/dist/migrate.d.ts +3 -2
- package/dist/migrate.d.ts.map +1 -1
- package/dist/migrate.js +25 -3
- package/dist/migrate.js.map +1 -1
- package/dist/migrator/access.d.ts.map +1 -1
- package/dist/migrator/access.js +65 -30
- package/dist/migrator/access.js.map +1 -1
- package/dist/migrator/call.d.ts.map +1 -1
- package/dist/migrator/call.js +298 -201
- package/dist/migrator/call.js.map +1 -1
- package/dist/migrator/concat.d.ts.map +1 -1
- package/dist/migrator/concat.js +15 -2
- package/dist/migrator/concat.js.map +1 -1
- package/dist/migrator/function.d.ts +6 -0
- package/dist/migrator/function.d.ts.map +1 -0
- package/dist/migrator/function.js +25 -0
- package/dist/migrator/function.js.map +1 -0
- package/dist/migrator/interface.d.ts +3 -1
- package/dist/migrator/interface.d.ts.map +1 -1
- package/dist/migrator/interface.js.map +1 -1
- package/dist/migrator/node.d.ts.map +1 -1
- package/dist/migrator/node.js +55 -7
- package/dist/migrator/node.js.map +1 -1
- package/dist/migrator/operator.d.ts.map +1 -1
- package/dist/migrator/operator.js +107 -60
- package/dist/migrator/operator.js.map +1 -1
- package/dist/migrator/serialize.d.ts +4 -0
- package/dist/migrator/serialize.d.ts.map +1 -0
- package/dist/migrator/serialize.js +21 -0
- package/dist/migrator/serialize.js.map +1 -0
- package/dist/migrator/special.d.ts.map +1 -1
- package/dist/migrator/special.js +31 -0
- package/dist/migrator/special.js.map +1 -1
- package/dist/migrator/state.d.ts +2 -2
- package/dist/migrator/state.d.ts.map +1 -1
- package/dist/migrator/state.js +30 -33
- package/dist/migrator/state.js.map +1 -1
- package/dist/migrator/symbol.d.ts.map +1 -1
- package/dist/migrator/symbol.js +34 -12
- package/dist/migrator/symbol.js.map +1 -1
- package/dist/migrator/to-type.d.ts.map +1 -1
- package/dist/migrator/to-type.js +21 -4
- package/dist/migrator/to-type.js.map +1 -1
- package/dist/migrator/utils.d.ts +6 -0
- package/dist/migrator/utils.d.ts.map +1 -1
- package/dist/migrator/utils.js +49 -1
- package/dist/migrator/utils.js.map +1 -1
- package/dist/parser.d.ts +2 -2
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +27 -8
- package/dist/parser.js.map +1 -1
- package/dist/re-exports.d.ts +4 -0
- package/dist/re-exports.d.ts.map +1 -0
- package/dist/re-exports.js +3 -0
- package/dist/re-exports.js.map +1 -0
- package/dist/scope.d.ts +17 -18
- package/dist/scope.d.ts.map +1 -1
- package/dist/scope.js +84 -53
- package/dist/scope.js.map +1 -1
- package/dist/type.d.ts +22 -10
- package/dist/type.d.ts.map +1 -1
- package/dist/type.js +21 -24
- package/dist/type.js.map +1 -1
- package/package.json +8 -5
- package/src/analyze.ts +20 -39
- package/src/definitions/argument.ts +3 -13
- package/src/definitions/constraint.ts +3 -3
- package/src/definitions/parameter-group.ts +4 -4
- package/src/definitions/parameter.ts +47 -24
- package/src/definitions/utils.ts +288 -0
- package/src/definitions/variable.ts +1 -1
- package/src/definitions.ts +1 -28
- package/src/eval.ts +16 -25
- package/src/expression.ts +16 -8
- package/src/index.ts +3 -1
- package/src/interface.ts +35 -0
- package/src/main.ts +232 -200
- package/src/migrate.ts +30 -6
- package/src/migrator/access.ts +68 -38
- package/src/migrator/call.ts +287 -190
- package/src/migrator/concat.ts +15 -2
- package/src/migrator/function.ts +27 -0
- package/src/migrator/interface.ts +3 -1
- package/src/migrator/node.ts +56 -6
- package/src/migrator/operator.ts +110 -64
- package/src/migrator/serialize.ts +21 -0
- package/src/migrator/special.ts +31 -0
- package/src/migrator/state.ts +30 -33
- package/src/migrator/symbol.ts +33 -12
- package/src/migrator/to-type.ts +23 -4
- package/src/migrator/utils.ts +49 -1
- package/src/parser.ts +33 -8
- package/src/re-exports.ts +47 -0
- package/src/scope.ts +101 -65
- package/src/type.ts +40 -25
- package/tests/analyze.ts +45 -6
- package/tests/compile.ts +65 -0
- package/tests/condition.ts +33 -17
- package/tests/definition.ts +237 -18
- package/tests/eval-complex.ts +19 -11
- package/tests/eval.ts +59 -12
- package/tests/import.ts +21 -7
- package/tests/main.ts +58 -0
- package/tests/migrate.ts +317 -0
- package/tests/scope.ts +3 -3
- package/tests/template.ts +36 -0
- package/dist/context.d.ts +0 -41
- package/dist/context.d.ts.map +0 -1
- package/dist/context.js +0 -18
- package/dist/context.js.map +0 -1
- package/src/context.ts +0 -54
package/tests/definition.ts
CHANGED
|
@@ -1,42 +1,261 @@
|
|
|
1
|
+
import { jest } from '@jest/globals';
|
|
1
2
|
import * as def from '../dist/definitions.js';
|
|
3
|
+
import { Expression } from '../dist/expression.js';
|
|
2
4
|
|
|
3
5
|
describe('definitions', () => {
|
|
4
6
|
it('should handle parameter', () => {
|
|
5
|
-
expect(def.
|
|
6
|
-
expect(def.isParameter(
|
|
7
|
+
expect(def.isParameter(null)).toBe(false);
|
|
8
|
+
expect(def.isParameter(() => void 0)).toBe(false);
|
|
9
|
+
expect(def.isParameter({ key: '', name: '', description: '', type: 'real', value: 0 })).toBe(true);
|
|
10
|
+
expect(def.isParameter({ type: 'label' })).toBe(false);
|
|
11
|
+
expect(def.isParameter({ name: '', description: '', items: [] })).toBe(false);
|
|
7
12
|
});
|
|
8
13
|
|
|
9
14
|
it('should handle parameter group', () => {
|
|
10
|
-
expect(def.
|
|
11
|
-
expect(def.isParameterGroup(
|
|
15
|
+
expect(def.isParameterGroup(null)).toBe(false);
|
|
16
|
+
expect(def.isParameterGroup(() => void 0)).toBe(false);
|
|
17
|
+
expect(def.isParameterGroup({ name: '', description: '', items: [] })).toBe(true);
|
|
18
|
+
expect(def.isParameterGroup({ items: [] })).toBe(false);
|
|
19
|
+
expect(def.isParameterGroup({ key: '', name: '', description: '', items: [] })).toBe(false);
|
|
12
20
|
});
|
|
13
21
|
|
|
14
22
|
it('should handle parameter decoration', () => {
|
|
15
|
-
expect(def.
|
|
16
|
-
expect(def.isParameterDecoration(
|
|
23
|
+
expect(def.isParameterDecoration(null)).toBe(false);
|
|
24
|
+
expect(def.isParameterDecoration(() => void 0)).toBe(false);
|
|
25
|
+
expect(def.isParameterDecoration({ type: 'label' })).toBe(true);
|
|
26
|
+
expect(def.isParameterDecoration({ name: '', description: '', items: [] })).toBe(false);
|
|
27
|
+
expect(def.isParameterDecoration({ key: '', name: '', description: '', type: 'real', value: 0 })).toBe(false);
|
|
17
28
|
});
|
|
18
29
|
|
|
19
30
|
it('should handle parameter decoration group', () => {
|
|
20
|
-
expect(def.
|
|
21
|
-
expect(def.isParameterDecorationGroup(
|
|
31
|
+
expect(def.isParameterDecorationGroup(null)).toBe(false);
|
|
32
|
+
expect(def.isParameterDecorationGroup(() => void 0)).toBe(false);
|
|
33
|
+
expect(def.isParameterDecorationGroup({ items: [] })).toBe(true);
|
|
34
|
+
expect(def.isParameterDecorationGroup({ name: '', description: '', items: [] })).toBe(false);
|
|
22
35
|
});
|
|
23
36
|
|
|
24
37
|
it('should handle variable', () => {
|
|
25
|
-
expect(def.
|
|
26
|
-
expect(def.isVariable(
|
|
38
|
+
expect(def.isVariable(null)).toBe(false);
|
|
39
|
+
expect(def.isVariable(() => void 0)).toBe(false);
|
|
40
|
+
expect(def.isVariable({ key: '', value: 0 })).toBe(true);
|
|
41
|
+
expect(def.isVariable({ key: '', name: '', description: '', type: 'real', value: 0 })).toBe(false);
|
|
27
42
|
});
|
|
28
43
|
|
|
29
44
|
it('should handle choice', () => {
|
|
30
|
-
expect(def.
|
|
31
|
-
expect(def.isChoice(
|
|
45
|
+
expect(def.isChoice(null)).toBe(false);
|
|
46
|
+
expect(def.isChoice(() => void 0)).toBe(false);
|
|
47
|
+
expect(def.isChoice({ name: '', description: '' })).toBe(true);
|
|
48
|
+
expect(def.isChoice({ key: null, name: '', description: '' })).toBe(true);
|
|
49
|
+
expect(def.isChoice({ key: '', name: '', description: '' })).toBe(true);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('should handle constraint', () => {
|
|
53
|
+
expect(def.isConstraint(null)).toBe(false);
|
|
54
|
+
expect(def.isConstraint(() => void 0)).toBe(false);
|
|
55
|
+
expect(def.isConstraint({ name: '', description: '' })).toBe(false);
|
|
56
|
+
expect(def.isConstraint({ key: null, name: '', description: '' })).toBe(false);
|
|
57
|
+
expect(def.isConstraint({ key: '', name: '', description: '' })).toBe(false);
|
|
58
|
+
expect(def.isConstraint({ message: '' })).toBe(false);
|
|
59
|
+
expect(def.isConstraint({ condition: '' })).toBe(false);
|
|
60
|
+
expect(def.isConstraint({ message: '', condition: '' })).toBe(true);
|
|
61
|
+
expect(def.isConstraint({ message: '', condition: '', level: 'error' })).toBe(true);
|
|
62
|
+
expect(def.isConstraint({ message: '', condition: '', level: 'error', messageData: '' })).toBe(true);
|
|
63
|
+
expect(def.isConstraint({ message: '', condition: '', messageData: {} })).toBe(true);
|
|
64
|
+
expect(def.isConstraint({ message: '', condition: '', messageData: null })).toBe(true);
|
|
65
|
+
expect(def.isConstraint({ message: '', condition: '', messageData: undefined })).toBe(true);
|
|
66
|
+
expect(def.isConstraint({ message: '', condition: '', messageData: () => void 0 })).toBe(true);
|
|
67
|
+
expect(def.isConstraint({ message: '', condition: '', messageData: 1 })).toBe(false);
|
|
68
|
+
});
|
|
32
69
|
|
|
33
|
-
|
|
34
|
-
|
|
70
|
+
it('should generate track id', () => {
|
|
71
|
+
const mockRandom = jest
|
|
72
|
+
.spyOn(Math, 'random')
|
|
73
|
+
.mockReturnValueOnce(0)
|
|
74
|
+
.mockReturnValueOnce(1 - 2 ** -53);
|
|
75
|
+
const id1 = def.generateTrackId();
|
|
76
|
+
const id2 = def.generateTrackId();
|
|
77
|
+
mockRandom.mockRestore();
|
|
78
|
+
expect(id1).toBe(1);
|
|
79
|
+
expect(id2).toBe(0x7fff_ffff);
|
|
80
|
+
});
|
|
35
81
|
|
|
36
|
-
|
|
37
|
-
expect
|
|
82
|
+
it('should convert argument value', () => {
|
|
83
|
+
// @ts-expect-error 未知类型
|
|
84
|
+
expect(def.toArgumentValue(undefined, { type: 'xxx', key: '', name: '', description: '', value: 1 })).toBe(
|
|
85
|
+
null,
|
|
86
|
+
);
|
|
87
|
+
expect(def.toArgumentValue(undefined, { type: 'real', key: '', name: '', description: '', value: 1 })).toBe(
|
|
88
|
+
null,
|
|
89
|
+
);
|
|
90
|
+
expect(def.toArgumentValue(null, { type: 'real', key: '', name: '', description: '', value: 1 })).toBe(null);
|
|
91
|
+
expect(def.toArgumentValue('12', { type: 'real', key: '', name: '', description: '', value: 1 })).toBe(12);
|
|
92
|
+
expect(def.toArgumentValue(null, { type: 'text', key: '', name: '', description: '', value: '1' })).toBe('');
|
|
93
|
+
expect(def.toArgumentValue(12, { type: 'text', key: '', name: '', description: '', value: '1' })).toBe('12');
|
|
94
|
+
expect(
|
|
95
|
+
def.toArgumentValue(null, { type: 'grouped', key: '', name: '', description: '', value: {}, items: [] }),
|
|
96
|
+
).toBe(null);
|
|
38
97
|
|
|
39
|
-
expect(
|
|
40
|
-
|
|
98
|
+
expect(
|
|
99
|
+
def.toArgumentValue(null, { type: 'choice', key: '', name: '', description: '', value: 1, choices: [] }),
|
|
100
|
+
).toBe(null);
|
|
101
|
+
expect(
|
|
102
|
+
def.toArgumentValue(null, {
|
|
103
|
+
type: 'choice',
|
|
104
|
+
key: '',
|
|
105
|
+
name: '',
|
|
106
|
+
description: '',
|
|
107
|
+
value: 1,
|
|
108
|
+
choices: [{ key: '0', name: '', description: '' }],
|
|
109
|
+
}),
|
|
110
|
+
).toBe('');
|
|
111
|
+
expect(
|
|
112
|
+
def.toArgumentValue(null, {
|
|
113
|
+
type: 'choice',
|
|
114
|
+
key: '',
|
|
115
|
+
name: '',
|
|
116
|
+
description: '',
|
|
117
|
+
value: 1,
|
|
118
|
+
choices: [
|
|
119
|
+
{ key: '0', name: '', description: '' },
|
|
120
|
+
{ key: 1, name: '', description: '' },
|
|
121
|
+
],
|
|
122
|
+
}),
|
|
123
|
+
).toBe('');
|
|
124
|
+
expect(def.toArgumentValue(null, { type: 'logical', key: '', name: '', description: '', value: 1 })).toBe(null);
|
|
125
|
+
expect(def.toArgumentValue('0', { type: 'logical', key: '', name: '', description: '', value: 1 })).toBe(0);
|
|
126
|
+
expect(
|
|
127
|
+
def.toArgumentValue(null, {
|
|
128
|
+
type: 'logical',
|
|
129
|
+
key: '',
|
|
130
|
+
name: '',
|
|
131
|
+
description: '',
|
|
132
|
+
value: false,
|
|
133
|
+
choices: [
|
|
134
|
+
{ key: 0, name: '', description: '' },
|
|
135
|
+
{ key: 1, name: '', description: '' },
|
|
136
|
+
],
|
|
137
|
+
}),
|
|
138
|
+
).toBe(null);
|
|
139
|
+
expect(
|
|
140
|
+
def.toArgumentValue(null, {
|
|
141
|
+
type: 'logical',
|
|
142
|
+
key: '',
|
|
143
|
+
name: '',
|
|
144
|
+
description: '',
|
|
145
|
+
value: true,
|
|
146
|
+
}),
|
|
147
|
+
).toBe(null);
|
|
148
|
+
expect(
|
|
149
|
+
def.toArgumentValue(null, {
|
|
150
|
+
type: 'logical',
|
|
151
|
+
key: '',
|
|
152
|
+
name: '',
|
|
153
|
+
description: '',
|
|
154
|
+
value: 'true',
|
|
155
|
+
}),
|
|
156
|
+
).toBe('');
|
|
157
|
+
expect(
|
|
158
|
+
def.toArgumentValue(null, {
|
|
159
|
+
type: 'logical',
|
|
160
|
+
key: '',
|
|
161
|
+
name: '',
|
|
162
|
+
description: '',
|
|
163
|
+
value: 'true',
|
|
164
|
+
choices: [
|
|
165
|
+
{ key: '0', name: '', description: '' },
|
|
166
|
+
{ key: '1', name: '', description: '' },
|
|
167
|
+
],
|
|
168
|
+
}),
|
|
169
|
+
).toBe('');
|
|
170
|
+
expect(
|
|
171
|
+
def.toArgumentValue(null, {
|
|
172
|
+
type: 'multiSelect',
|
|
173
|
+
key: '',
|
|
174
|
+
name: '',
|
|
175
|
+
description: '',
|
|
176
|
+
value: [1],
|
|
177
|
+
choices: [],
|
|
178
|
+
}),
|
|
179
|
+
).toStrictEqual([]);
|
|
180
|
+
expect(
|
|
181
|
+
def.toArgumentValue(1, {
|
|
182
|
+
type: 'multiSelect',
|
|
183
|
+
key: '',
|
|
184
|
+
name: '',
|
|
185
|
+
description: '',
|
|
186
|
+
value: [1],
|
|
187
|
+
choices: [],
|
|
188
|
+
}),
|
|
189
|
+
).toStrictEqual([1]);
|
|
190
|
+
expect(
|
|
191
|
+
def.toArgumentValue('', {
|
|
192
|
+
type: 'multiSelect',
|
|
193
|
+
key: '',
|
|
194
|
+
name: '',
|
|
195
|
+
description: '',
|
|
196
|
+
value: [1],
|
|
197
|
+
choices: [],
|
|
198
|
+
}),
|
|
199
|
+
).toStrictEqual(null);
|
|
200
|
+
expect(
|
|
201
|
+
def.toArgumentValue('', {
|
|
202
|
+
type: 'multiSelect',
|
|
203
|
+
key: '',
|
|
204
|
+
name: '',
|
|
205
|
+
description: '',
|
|
206
|
+
value: [1],
|
|
207
|
+
choices: Expression(''),
|
|
208
|
+
}),
|
|
209
|
+
).toStrictEqual(null);
|
|
210
|
+
expect(
|
|
211
|
+
def.toArgumentValue(['', '1', ' 2 '], {
|
|
212
|
+
type: 'multiSelect',
|
|
213
|
+
key: '',
|
|
214
|
+
name: '',
|
|
215
|
+
description: '',
|
|
216
|
+
value: [1],
|
|
217
|
+
choices: [],
|
|
218
|
+
}),
|
|
219
|
+
).toStrictEqual(null);
|
|
220
|
+
expect(
|
|
221
|
+
def.toArgumentValue(['0', '1', ' 2 '], {
|
|
222
|
+
type: 'multiSelect',
|
|
223
|
+
key: '',
|
|
224
|
+
name: '',
|
|
225
|
+
description: '',
|
|
226
|
+
value: [1],
|
|
227
|
+
choices: [],
|
|
228
|
+
}),
|
|
229
|
+
).toStrictEqual([0, 1, 2]);
|
|
230
|
+
expect(
|
|
231
|
+
def.toArgumentValue(['0', '1', ' 2 '], {
|
|
232
|
+
type: 'multiSelect',
|
|
233
|
+
key: '',
|
|
234
|
+
name: '',
|
|
235
|
+
description: '',
|
|
236
|
+
value: [],
|
|
237
|
+
choices: [],
|
|
238
|
+
}),
|
|
239
|
+
).toStrictEqual([0, 1, 2]);
|
|
240
|
+
expect(
|
|
241
|
+
def.toArgumentValue([1, 2], {
|
|
242
|
+
type: 'multiSelect',
|
|
243
|
+
key: '',
|
|
244
|
+
name: '',
|
|
245
|
+
description: '',
|
|
246
|
+
value: ['1'],
|
|
247
|
+
choices: [],
|
|
248
|
+
}),
|
|
249
|
+
).toStrictEqual(['1', '2']);
|
|
250
|
+
expect(
|
|
251
|
+
def.toArgumentValue(['', '1', ' 2 '], {
|
|
252
|
+
type: 'multiSelect',
|
|
253
|
+
key: '',
|
|
254
|
+
name: '',
|
|
255
|
+
description: '',
|
|
256
|
+
value: [1],
|
|
257
|
+
choices: Expression(''),
|
|
258
|
+
}),
|
|
259
|
+
).toStrictEqual(null);
|
|
41
260
|
});
|
|
42
261
|
});
|
package/tests/eval-complex.ts
CHANGED
|
@@ -44,18 +44,15 @@ describe('Evaluator should work correctly', () => {
|
|
|
44
44
|
const result = e.evaluate(Expression('a.0'), s);
|
|
45
45
|
expect(result).toBe(36);
|
|
46
46
|
});
|
|
47
|
-
it('should eval deep with extern', () => {
|
|
47
|
+
it('should not eval deep with extern', () => {
|
|
48
48
|
const s = new Scope(
|
|
49
49
|
{
|
|
50
|
-
a: new VmExtern([Expression('
|
|
51
|
-
b: new VmExtern([Expression('c.0 + d.0')]),
|
|
52
|
-
c: new VmExtern([12]),
|
|
53
|
-
d: new VmExtern([Expression('c.0')]),
|
|
50
|
+
a: new VmExtern([Expression('1')]),
|
|
54
51
|
},
|
|
55
52
|
false,
|
|
56
53
|
);
|
|
57
|
-
const result = e.evaluate(Expression('a.0'), s);
|
|
58
|
-
expect(result).
|
|
54
|
+
const result = e.evaluate<VmExtern>(Expression('a.0'), s);
|
|
55
|
+
expect(result?.value).toStrictEqual(Expression('1'));
|
|
59
56
|
});
|
|
60
57
|
it('should eval deep with compiled expression', () => {
|
|
61
58
|
const s = new Scope(
|
|
@@ -105,7 +102,7 @@ describe('Evaluator should work correctly', () => {
|
|
|
105
102
|
const result = e.evaluate(Expression('a + a + a + a + a + a + a + a + a + a'), s);
|
|
106
103
|
expect(result).toBe(10);
|
|
107
104
|
});
|
|
108
|
-
it('should report loop', () => {
|
|
105
|
+
it('should report loop by scope', () => {
|
|
109
106
|
const s = new Scope(
|
|
110
107
|
{
|
|
111
108
|
a: Expression('b'),
|
|
@@ -114,6 +111,17 @@ describe('Evaluator should work correctly', () => {
|
|
|
114
111
|
},
|
|
115
112
|
true,
|
|
116
113
|
);
|
|
114
|
+
expect(() => e.evaluate(Expression('a'), s)).toThrow(/Execution recursion exceeds limit/);
|
|
115
|
+
});
|
|
116
|
+
it('should report loop by mirascript', () => {
|
|
117
|
+
const s = new Scope(
|
|
118
|
+
{
|
|
119
|
+
a: Expression('fn x{b}x()'),
|
|
120
|
+
b: Expression('fn x{c}x()'),
|
|
121
|
+
c: Expression('fn x{a}x()'),
|
|
122
|
+
},
|
|
123
|
+
true,
|
|
124
|
+
);
|
|
117
125
|
expect(() => e.evaluate(Expression('a'), s)).toThrow(/Maximum call depth exceeded/);
|
|
118
126
|
});
|
|
119
127
|
|
|
@@ -132,7 +140,7 @@ describe('Evaluator should work correctly', () => {
|
|
|
132
140
|
a: new ArrayBuffer(0),
|
|
133
141
|
v: new DataView(new ArrayBuffer(0)),
|
|
134
142
|
test() {
|
|
135
|
-
expect(this).toBeProxy();
|
|
143
|
+
expect(this).not.toBeProxy();
|
|
136
144
|
expect(this.d).not.toBeProxy();
|
|
137
145
|
expect(this.r).not.toBeProxy();
|
|
138
146
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
@@ -144,7 +152,7 @@ describe('Evaluator should work correctly', () => {
|
|
|
144
152
|
},
|
|
145
153
|
});
|
|
146
154
|
const s = new Scope({ o }, true);
|
|
147
|
-
expect(e.evaluate(Expression('o.test()'), s)).
|
|
148
|
-
expect(e.evaluate(Expression('o.z'), s)).
|
|
155
|
+
expect(e.evaluate<VmExtern>(Expression('o.test()'), s)?.value).toStrictEqual(Expression('o.y+o.x.p'));
|
|
156
|
+
expect(e.evaluate<VmExtern>(Expression('o.z'), s)?.value).toStrictEqual(Expression('o.y+o.x.p'));
|
|
149
157
|
});
|
|
150
158
|
});
|
package/tests/eval.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
import { Evaluator, Expression, Scope } from '../dist/index.js';
|
|
1
|
+
import { Evaluator, Expression, Scope, VmFunction } from '../dist/index.js';
|
|
2
2
|
|
|
3
|
-
const e = new Evaluator(
|
|
3
|
+
const e = new Evaluator({
|
|
4
|
+
logger: {
|
|
5
|
+
warn: () => void 0,
|
|
6
|
+
error: () => void 0,
|
|
7
|
+
info: () => void 0,
|
|
8
|
+
debug: () => void 0,
|
|
9
|
+
},
|
|
10
|
+
});
|
|
4
11
|
const s = new Scope({}, false);
|
|
12
|
+
const st = new Scope(null, true);
|
|
5
13
|
|
|
6
|
-
describe('Evaluator should work correctly', () => {
|
|
14
|
+
describe('Evaluator.evaluate should work correctly', () => {
|
|
7
15
|
it('should eval const', () => {
|
|
8
16
|
const result = e.evaluate(Expression('12'), s);
|
|
9
17
|
expect(result).toBe(12);
|
|
@@ -16,11 +24,39 @@ describe('Evaluator should work correctly', () => {
|
|
|
16
24
|
|
|
17
25
|
it('should eval error', () => {
|
|
18
26
|
const result = e.evaluate(Expression('exp+++'), s);
|
|
19
|
-
expect(result).toBe(
|
|
27
|
+
expect(result).toBe(null);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should eval null', () => {
|
|
31
|
+
const result = e.evaluate(null, s);
|
|
32
|
+
expect(result).toBe(null);
|
|
33
|
+
});
|
|
34
|
+
it('should eval undefined', () => {
|
|
35
|
+
const result = e.evaluate(undefined, s);
|
|
36
|
+
expect(result).toBe(null);
|
|
37
|
+
});
|
|
38
|
+
it('should eval value', () => {
|
|
39
|
+
{
|
|
40
|
+
const result = e.evaluate(1, s);
|
|
41
|
+
expect(result).toBe(1);
|
|
42
|
+
}
|
|
43
|
+
{
|
|
44
|
+
const result = e.evaluate('', s);
|
|
45
|
+
expect(result).toBe('');
|
|
46
|
+
}
|
|
47
|
+
{
|
|
48
|
+
const result = e.evaluate(false, s);
|
|
49
|
+
expect(result).toBe(false);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
it('should eval vm function', () => {
|
|
53
|
+
const f = VmFunction(() => 1);
|
|
54
|
+
const result = e.evaluate(f, s);
|
|
55
|
+
expect(result).toBe(f);
|
|
20
56
|
});
|
|
21
57
|
});
|
|
22
58
|
|
|
23
|
-
describe('Evaluator should convert result', () => {
|
|
59
|
+
describe('Evaluator.evaluate should convert result', () => {
|
|
24
60
|
it('should eval const', () => {
|
|
25
61
|
const result = e.evaluate(Expression('12', 'string'), s);
|
|
26
62
|
expect(result).toBe('12');
|
|
@@ -31,12 +67,23 @@ describe('Evaluator should convert result', () => {
|
|
|
31
67
|
expect(result).toBe(Math.exp(2).toString());
|
|
32
68
|
});
|
|
33
69
|
|
|
34
|
-
it('should not convert
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
70
|
+
it('should not convert defaults', () => {
|
|
71
|
+
{
|
|
72
|
+
const result = e.evaluate(Expression('nil', 's'), s, 1);
|
|
73
|
+
expect(result).toBe(1);
|
|
74
|
+
}
|
|
75
|
+
{
|
|
76
|
+
// syntax error
|
|
77
|
+
expect(() => e.evaluate(Expression('exp+++', 's'), undefined, 1)).toThrow();
|
|
78
|
+
}
|
|
79
|
+
{
|
|
80
|
+
// syntax error cached
|
|
81
|
+
expect(() => e.evaluate(Expression('exp+++', 's'), st)).toThrow();
|
|
82
|
+
}
|
|
83
|
+
{
|
|
84
|
+
// runtime error
|
|
85
|
+
const result = e.evaluate(Expression('x() + 1', 's'), s, 1);
|
|
86
|
+
expect(result).toBe(1);
|
|
87
|
+
}
|
|
41
88
|
});
|
|
42
89
|
});
|
package/tests/import.ts
CHANGED
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
import { VmFunction } from '@mirascript/mirascript';
|
|
2
2
|
import { Evaluator, Expression, Scope } from '../dist/index.js';
|
|
3
|
-
import { lib } from '@mirascript/mirascript/subtle';
|
|
3
|
+
import { convert, lib } from '@mirascript/mirascript/subtle';
|
|
4
4
|
|
|
5
|
-
const e = new Evaluator(
|
|
6
|
-
|
|
5
|
+
const e = new Evaluator({
|
|
6
|
+
logger: {
|
|
7
|
+
warn: () => void 0,
|
|
8
|
+
error: () => void 0,
|
|
9
|
+
info: () => void 0,
|
|
10
|
+
debug: () => void 0,
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
const e2 = new Evaluator({
|
|
14
|
+
logger: {
|
|
15
|
+
warn: () => void 0,
|
|
16
|
+
error: () => void 0,
|
|
17
|
+
info: () => void 0,
|
|
18
|
+
debug: () => void 0,
|
|
19
|
+
},
|
|
20
|
+
});
|
|
7
21
|
const s = new Scope(undefined, false);
|
|
8
22
|
|
|
9
23
|
describe('Import should work correctly', () => {
|
|
@@ -11,21 +25,21 @@ describe('Import should work correctly', () => {
|
|
|
11
25
|
e.import({ add: (x: number, y: number) => x + y });
|
|
12
26
|
expect(e.evaluate(Expression('add(1,2)'), s)).toBe(3);
|
|
13
27
|
expect(e.evaluate(Expression('add::type()'), s)).toBe('extern');
|
|
14
|
-
expect(e2.evaluate(Expression('add(1,2)'), s)).toBe(
|
|
15
|
-
expect(e2.evaluate(Expression('add::type()'), s)).toBe(
|
|
28
|
+
expect(e2.evaluate(Expression('add(1,2)'), s)).toBe(null);
|
|
29
|
+
expect(e2.evaluate(Expression('add::type()'), s)).toBe(null);
|
|
16
30
|
});
|
|
17
31
|
|
|
18
32
|
it('can remove modules', () => {
|
|
19
33
|
e.import({ add: (x: number, y: number) => x + y });
|
|
20
34
|
expect(e.evaluate(Expression('add(1,2)'), s)).toBe(3);
|
|
21
35
|
e.import({ add: undefined });
|
|
22
|
-
expect(e.evaluate(Expression('add(1,2)'), s)).toBe(
|
|
36
|
+
expect(e.evaluate(Expression('add(1,2)'), s)).toBe(null);
|
|
23
37
|
});
|
|
24
38
|
|
|
25
39
|
it('can replace modules', () => {
|
|
26
40
|
e.import({ add: (x: number, y: number) => x + y });
|
|
27
41
|
expect(e.evaluate(Expression('add::type()'), s)).toBe('extern');
|
|
28
|
-
e.import({ add: VmFunction((x, y) =>
|
|
42
|
+
e.import({ add: VmFunction((x, y) => convert.toNumber(x, 0) + convert.toNumber(y, 0)) });
|
|
29
43
|
expect(e.evaluate(Expression('add::type()'), s)).toBe('function');
|
|
30
44
|
});
|
|
31
45
|
});
|
package/tests/main.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Evaluator } from '../dist/main.js';
|
|
2
|
+
|
|
3
|
+
describe('Evaluator', () => {
|
|
4
|
+
it('should have logger', () => {
|
|
5
|
+
expect(new Evaluator().logger).toBeTruthy();
|
|
6
|
+
expect(new Evaluator(null).logger).toBeTruthy();
|
|
7
|
+
expect(new Evaluator({}).logger).toBeTruthy();
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
describe('can evaluate choices', () => {
|
|
11
|
+
const e = new Evaluator();
|
|
12
|
+
|
|
13
|
+
it('on logical type', () => {
|
|
14
|
+
const c0 = e.evaluateChoices({ type: 'logical', value: null as never }, null);
|
|
15
|
+
expect(c0.length).toBe(2);
|
|
16
|
+
expect(c0[0].key).toBe(false);
|
|
17
|
+
expect(c0[1].key).toBe(true);
|
|
18
|
+
|
|
19
|
+
const c1 = e.evaluateChoices(
|
|
20
|
+
{
|
|
21
|
+
type: 'logical',
|
|
22
|
+
// @ts-expect-error Incomplete choice definition
|
|
23
|
+
choices: [{}, { key: true, name: 'Yes' }],
|
|
24
|
+
value: null as never,
|
|
25
|
+
},
|
|
26
|
+
null,
|
|
27
|
+
);
|
|
28
|
+
expect(c1.length).toBe(2);
|
|
29
|
+
expect(c1[0].key).toBe(false);
|
|
30
|
+
expect(c1[1].key).toBe(true);
|
|
31
|
+
expect(c1[0].name).toBe('');
|
|
32
|
+
expect(c1[1].name).toBe('Yes');
|
|
33
|
+
|
|
34
|
+
const c2 = e.evaluateChoices(
|
|
35
|
+
{
|
|
36
|
+
type: 'logical',
|
|
37
|
+
// @ts-expect-error Incomplete choice definition
|
|
38
|
+
choices: [{ key: 0 }, { key: '1' }, { key: 2 }],
|
|
39
|
+
value: null as never,
|
|
40
|
+
},
|
|
41
|
+
null,
|
|
42
|
+
);
|
|
43
|
+
expect(c2.length).toBe(2);
|
|
44
|
+
expect(c2[0].key).toBe(0);
|
|
45
|
+
expect(c2[1].key).toBe(1);
|
|
46
|
+
|
|
47
|
+
const c3 = e.evaluateChoices({ type: 'logical', choices: [], value: 0 }, null);
|
|
48
|
+
expect(c3.length).toBe(2);
|
|
49
|
+
expect(c3[0].key).toBe(0);
|
|
50
|
+
expect(c3[1].key).toBe(1);
|
|
51
|
+
|
|
52
|
+
const c4 = e.evaluateChoices({ type: 'logical', value: 'x' }, null);
|
|
53
|
+
expect(c4.length).toBe(2);
|
|
54
|
+
expect(c4[0].key).toBe('0');
|
|
55
|
+
expect(c4[1].key).toBe('1');
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
});
|