@cloudpss/expression 0.6.0-alpha.9 → 0.6.0

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.
Files changed (157) hide show
  1. package/dist/analyze.d.ts +6 -3
  2. package/dist/analyze.d.ts.map +1 -1
  3. package/dist/analyze.js +13 -33
  4. package/dist/analyze.js.map +1 -1
  5. package/dist/definitions/argument.d.ts +3 -11
  6. package/dist/definitions/argument.d.ts.map +1 -1
  7. package/dist/definitions/constraint.d.ts +2 -2
  8. package/dist/definitions/constraint.d.ts.map +1 -1
  9. package/dist/definitions/constraint.js +1 -1
  10. package/dist/definitions/constraint.js.map +1 -1
  11. package/dist/definitions/parameter-group.js +4 -4
  12. package/dist/definitions/parameter-group.js.map +1 -1
  13. package/dist/definitions/parameter.d.ts +22 -14
  14. package/dist/definitions/parameter.d.ts.map +1 -1
  15. package/dist/definitions/parameter.js +10 -1
  16. package/dist/definitions/parameter.js.map +1 -1
  17. package/dist/definitions/utils.d.ts +28 -0
  18. package/dist/definitions/utils.d.ts.map +1 -0
  19. package/dist/definitions/utils.js +272 -0
  20. package/dist/definitions/utils.js.map +1 -0
  21. package/dist/definitions/variable.js +1 -1
  22. package/dist/definitions/variable.js.map +1 -1
  23. package/dist/definitions.d.ts +1 -2
  24. package/dist/definitions.d.ts.map +1 -1
  25. package/dist/definitions.js +1 -1
  26. package/dist/definitions.js.map +1 -1
  27. package/dist/eval.d.ts +3 -5
  28. package/dist/eval.d.ts.map +1 -1
  29. package/dist/eval.js +12 -20
  30. package/dist/eval.js.map +1 -1
  31. package/dist/expression.d.ts +10 -4
  32. package/dist/expression.d.ts.map +1 -1
  33. package/dist/expression.js +6 -6
  34. package/dist/expression.js.map +1 -1
  35. package/dist/index.d.ts +3 -1
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +1 -0
  38. package/dist/index.js.map +1 -1
  39. package/dist/interface.d.ts +30 -0
  40. package/dist/interface.d.ts.map +1 -0
  41. package/dist/interface.js +6 -0
  42. package/dist/interface.js.map +1 -0
  43. package/dist/main.d.ts +41 -28
  44. package/dist/main.d.ts.map +1 -1
  45. package/dist/main.js +165 -149
  46. package/dist/main.js.map +1 -1
  47. package/dist/migrate.d.ts +1 -1
  48. package/dist/migrate.d.ts.map +1 -1
  49. package/dist/migrate.js +25 -4
  50. package/dist/migrate.js.map +1 -1
  51. package/dist/migrator/access.d.ts.map +1 -1
  52. package/dist/migrator/access.js +64 -29
  53. package/dist/migrator/access.js.map +1 -1
  54. package/dist/migrator/call.d.ts.map +1 -1
  55. package/dist/migrator/call.js +298 -201
  56. package/dist/migrator/call.js.map +1 -1
  57. package/dist/migrator/concat.d.ts.map +1 -1
  58. package/dist/migrator/concat.js +15 -2
  59. package/dist/migrator/concat.js.map +1 -1
  60. package/dist/migrator/function.d.ts +6 -0
  61. package/dist/migrator/function.d.ts.map +1 -0
  62. package/dist/migrator/function.js +25 -0
  63. package/dist/migrator/function.js.map +1 -0
  64. package/dist/migrator/interface.d.ts +3 -1
  65. package/dist/migrator/interface.d.ts.map +1 -1
  66. package/dist/migrator/interface.js.map +1 -1
  67. package/dist/migrator/node.d.ts.map +1 -1
  68. package/dist/migrator/node.js +55 -7
  69. package/dist/migrator/node.js.map +1 -1
  70. package/dist/migrator/operator.d.ts.map +1 -1
  71. package/dist/migrator/operator.js +107 -60
  72. package/dist/migrator/operator.js.map +1 -1
  73. package/dist/migrator/serialize.d.ts +4 -0
  74. package/dist/migrator/serialize.d.ts.map +1 -0
  75. package/dist/migrator/serialize.js +21 -0
  76. package/dist/migrator/serialize.js.map +1 -0
  77. package/dist/migrator/special.d.ts.map +1 -1
  78. package/dist/migrator/special.js +31 -0
  79. package/dist/migrator/special.js.map +1 -1
  80. package/dist/migrator/state.d.ts +4 -4
  81. package/dist/migrator/state.d.ts.map +1 -1
  82. package/dist/migrator/state.js +29 -31
  83. package/dist/migrator/state.js.map +1 -1
  84. package/dist/migrator/symbol.d.ts.map +1 -1
  85. package/dist/migrator/symbol.js +34 -12
  86. package/dist/migrator/symbol.js.map +1 -1
  87. package/dist/migrator/to-type.d.ts.map +1 -1
  88. package/dist/migrator/to-type.js +21 -4
  89. package/dist/migrator/to-type.js.map +1 -1
  90. package/dist/migrator/utils.d.ts +6 -0
  91. package/dist/migrator/utils.d.ts.map +1 -1
  92. package/dist/migrator/utils.js +48 -1
  93. package/dist/migrator/utils.js.map +1 -1
  94. package/dist/parser.d.ts +2 -2
  95. package/dist/parser.d.ts.map +1 -1
  96. package/dist/parser.js +27 -8
  97. package/dist/parser.js.map +1 -1
  98. package/dist/re-exports.d.ts +4 -0
  99. package/dist/re-exports.d.ts.map +1 -0
  100. package/dist/re-exports.js +3 -0
  101. package/dist/re-exports.js.map +1 -0
  102. package/dist/scope.d.ts +16 -17
  103. package/dist/scope.d.ts.map +1 -1
  104. package/dist/scope.js +127 -66
  105. package/dist/scope.js.map +1 -1
  106. package/dist/type.d.ts +22 -10
  107. package/dist/type.d.ts.map +1 -1
  108. package/dist/type.js +21 -24
  109. package/dist/type.js.map +1 -1
  110. package/package.json +8 -5
  111. package/src/analyze.ts +20 -39
  112. package/src/definitions/argument.ts +3 -13
  113. package/src/definitions/constraint.ts +3 -3
  114. package/src/definitions/parameter-group.ts +4 -4
  115. package/src/definitions/parameter.ts +47 -24
  116. package/src/definitions/utils.ts +288 -0
  117. package/src/definitions/variable.ts +1 -1
  118. package/src/definitions.ts +1 -28
  119. package/src/eval.ts +16 -25
  120. package/src/expression.ts +16 -8
  121. package/src/index.ts +3 -1
  122. package/src/interface.ts +35 -0
  123. package/src/main.ts +232 -200
  124. package/src/migrate.ts +27 -4
  125. package/src/migrator/access.ts +67 -37
  126. package/src/migrator/call.ts +287 -190
  127. package/src/migrator/concat.ts +15 -2
  128. package/src/migrator/function.ts +27 -0
  129. package/src/migrator/interface.ts +3 -1
  130. package/src/migrator/node.ts +56 -6
  131. package/src/migrator/operator.ts +110 -64
  132. package/src/migrator/serialize.ts +21 -0
  133. package/src/migrator/special.ts +31 -0
  134. package/src/migrator/state.ts +31 -34
  135. package/src/migrator/symbol.ts +33 -12
  136. package/src/migrator/to-type.ts +23 -4
  137. package/src/migrator/utils.ts +48 -1
  138. package/src/parser.ts +33 -8
  139. package/src/re-exports.ts +47 -0
  140. package/src/scope.ts +146 -77
  141. package/src/type.ts +40 -25
  142. package/tests/analyze.ts +45 -6
  143. package/tests/compile.ts +65 -0
  144. package/tests/condition.ts +33 -17
  145. package/tests/definition.ts +237 -18
  146. package/tests/eval-complex.ts +79 -13
  147. package/tests/eval.ts +59 -12
  148. package/tests/import.ts +21 -7
  149. package/tests/main.ts +58 -0
  150. package/tests/migrate.ts +317 -0
  151. package/tests/scope.ts +3 -3
  152. package/tests/template.ts +36 -0
  153. package/dist/context.d.ts +0 -41
  154. package/dist/context.d.ts.map +0 -1
  155. package/dist/context.js +0 -18
  156. package/dist/context.js.map +0 -1
  157. package/src/context.ts +0 -54
@@ -0,0 +1,317 @@
1
+ import { migrateMathJs } from '@cloudpss/expression/migrate';
2
+ import type { ExpressionSource } from '../dist/expression.js';
3
+ import { Scope } from '../dist/scope.js';
4
+ import { Evaluator, Expression, VmError } from '../dist/index.js';
5
+ import dedent from 'dedent';
6
+
7
+ const s = new Scope({
8
+ a: [1, 2, 3],
9
+ m: [
10
+ [1, 2],
11
+ [3, 4],
12
+ ],
13
+ f: 1,
14
+ s: 'abc',
15
+ b: false,
16
+ o: {
17
+ x: 1,
18
+ y: 2,
19
+ },
20
+ type: 'keyword',
21
+ });
22
+ const e = new Evaluator();
23
+
24
+ describe('migrate', () => {
25
+ it('should migrate constant expressions', () => {
26
+ const m = (e: string) => migrateMathJs(e as ExpressionSource, false, undefined);
27
+ expect(m('')).toBe('');
28
+ expect(m(' ')).toBe('');
29
+ expect(m('undefined')).toBe('');
30
+ expect(m('null')).toBe('nil');
31
+ expect(m('true')).toBe('true');
32
+ expect(m('false')).toBe('false');
33
+ expect(m('123')).toBe('123');
34
+ expect(m('-123.45e+6')).toBe('-123.45e+6');
35
+ expect(m('+123.45e-6')).toBe('+123.45e-6');
36
+ expect(m('.45e-6')).toBe('4.5e-7');
37
+ });
38
+
39
+ it.each([
40
+ ['sin(0)', 'sin(0)', 0],
41
+ ['sin(f)', 'sin(f)', Math.sin(1)],
42
+ ['f', 'f', 1],
43
+ ['o == null', 'o == nil', false],
44
+ ['o == undefined', 'o == nil', false],
45
+ ['o == undefined', 'o == nil', false],
46
+ ['b == false', 'b =~ 0', true],
47
+ ['true != b', '1 !~ b', true],
48
+ ['f == true', 'f =~ 1', true],
49
+ ['false == f', '0 =~ f', false],
50
+ ['0 <= f + 1 <= 2', 'f + 1 is 0..2', true],
51
+ ['$a', '$a', VmError],
52
+ ['$a + 1', 'matrix.add($a, 1)', VmError],
53
+ ['size(a)[1]', 'len(a)', 3],
54
+ ['size(s)[1]', 'len(chars(s))', 3],
55
+ ['(a).length', 'len((a))', 3],
56
+ ['(s).length', 'len(chars((s)))', 3],
57
+ ['count(s)', 'len(chars(s))', 3],
58
+ ['b ? true : false', 'b', false],
59
+ ['b ? false : true', '!b', true],
60
+ ['is(f, "string") ? count(f) != 0 : false', "type(f) == 'string' && f != ''", false],
61
+ ['is(f, "string") ? equalText(f, "xyz") : false', "f == 'xyz'", false],
62
+ ['b ? 1 : 2', 'if b { 1 } else { 2 }', 2],
63
+ ['f >0', 'f > 0', true],
64
+ ['f >=0', 'f >= 0', true],
65
+ ['f <0', 'f < 0', false],
66
+ ['f == 1', 'f =~ 1', true],
67
+ ['f != 1', 'f !~ 1', false],
68
+ ['1<f<2', '1 < f && f < 2', false],
69
+ ['1 + 2 + f', '1 + 2 + f', 4],
70
+ ['PI', 'PI', Math.PI],
71
+ ['pi', 'PI', Math.PI],
72
+ ['E', 'E', Math.E],
73
+ ['e', 'E', Math.E],
74
+ ['[1,2,3]', '[1, 2, 3]', [1, 2, 3]],
75
+ ['[1;2;3]', '[[1], [2], [3]]', [[1], [2], [3]]],
76
+ ['{ x: 1, y: 2 }', '(x: 1, y: 2)', { x: 1, y: 2 }],
77
+ ['{ x: f, y: b }', '(x: f, y: b)', { x: 1, y: false }],
78
+ ['equalText("a", "b")', "'a' == 'b'", false],
79
+ ['equalText("a", s)', "'a' == s", false],
80
+ ['equalText(s, "b")', "s == 'b'", false],
81
+ ['equalText(s, f)', 's == to_string(f)', false],
82
+ ['b | b', 'to_number(b || b)', 0],
83
+ ['b & b', 'to_number(b && b)', 0],
84
+ ['not b', '!b', true],
85
+ ['12!', 'factorial(12)', 479_001_600],
86
+ ['- b', '-b', -0],
87
+ ['+ b', '+b', +0],
88
+ ['- f', '-f', -1],
89
+ ['b ^| f', 'b_xor(b, f)', 1],
90
+ ['b ^| (not b)', 'to_number(b != (!b))', 1],
91
+ [
92
+ 'not b xor f + 1',
93
+ dedent`
94
+ return (!b) != @@to_boolean(f + 1);
95
+ // # 帮助函数
96
+ fn @@to_boolean { if it is nil { nil } else { it != '' && it != '0' && it != 0 && it is not nan && it != false } }
97
+ // # 原始 math.js 表达式
98
+ // not b xor f + 1`,
99
+ false,
100
+ ],
101
+ ['size(f)', 'matrix.size(f)', []],
102
+ ['size(m)', 'matrix.size(m)', [2, 2]],
103
+ [`[1,2,3] == f`, `[1, 2, 3]::map(fn { it =~ f })`, [true, false, false]],
104
+ [`$V != [1,2,3]`, `[1, 2, 3]::map(fn { $V !~ it })`, VmError],
105
+ [
106
+ 'u.length',
107
+ dedent`
108
+ return @@length(u);
109
+ // # 帮助函数
110
+ fn @@length(x) { if type(x) == 'string' { len(chars(x)) } else if type(x) == 'array' { len(x) } else { x.length } }
111
+ // # 转换日志
112
+ // - W: 符号 'u' 未定义
113
+ // # 原始 math.js 表达式
114
+ // u.length`,
115
+ VmError,
116
+ ],
117
+ ['o["x"]', 'o.x', 1],
118
+ ['o.x', 'o.x', 1],
119
+ [
120
+ 'o[s]',
121
+ dedent`
122
+ return o[@@index(s)];
123
+ // # 帮助函数
124
+ fn @@index(index) { if type(index) == 'number' { index - 1 } else { index } }
125
+ // # 原始 math.js 表达式
126
+ // o[s]`,
127
+ null,
128
+ ],
129
+ [
130
+ 'o[f]',
131
+ dedent`
132
+ return o[@@index(f)];
133
+ // # 帮助函数
134
+ fn @@index(index) { if type(index) == 'number' { index - 1 } else { index } }
135
+ // # 原始 math.js 表达式
136
+ // o[f]`,
137
+ null,
138
+ ],
139
+ [`{x:1,y:2}['x']`, `(x: 1, y: 2).x`, 1],
140
+ [`{x:1,y:2}[s]`, `(x: 1, y: 2)[s]`, null],
141
+ [`[1,2,3][f]`, `[1, 2, 3][f - 1]`, 1],
142
+ ['"abc"[1]', "chars('abc')[0]", 'a'],
143
+ ['s[1]', 'chars(s)[0]', 'a'],
144
+ ['[1,2,3][2]', '[1, 2, 3][1]', 2],
145
+ ['a[2]', 'a[1]', 2],
146
+ [
147
+ 'a[u]',
148
+ dedent`
149
+ return a[@@index(u)];
150
+ // # 帮助函数
151
+ fn @@index(index) { if type(index) == 'number' { index - 1 } else { index } }
152
+ // # 转换日志
153
+ // - W: 符号 'u' 未定义
154
+ // # 原始 math.js 表达式
155
+ // a[u]`,
156
+ VmError,
157
+ ],
158
+ [
159
+ 'u[1]',
160
+ dedent`
161
+ return @@maybe_chars(u)[0];
162
+ // # 帮助函数
163
+ fn @@maybe_chars(x) { if type(x) == 'string' { chars(x) } else { x } }
164
+ // # 转换日志
165
+ // - W: 符号 'u' 未定义
166
+ // # 原始 math.js 表达式
167
+ // u[1]`,
168
+ VmError,
169
+ ],
170
+ [
171
+ 'm[1,2]',
172
+ dedent`
173
+ m[0][1]
174
+ // # 转换日志
175
+ // - W: 多维索引已拆分为多次单维索引
176
+ // # 原始 math.js 表达式
177
+ // m[1,2]`,
178
+ 2,
179
+ ],
180
+ [
181
+ 'm[f,2]',
182
+ dedent`
183
+ m[f - 1][1]
184
+ // # 转换日志
185
+ // - W: 多维索引已拆分为多次单维索引
186
+ // # 原始 math.js 表达式
187
+ // m[f,2]`,
188
+ 2,
189
+ ],
190
+ [
191
+ 'filter(x) = x > 1; a.filter(filter)',
192
+ dedent`
193
+ fn filter(x) { matrix.entrywise(x, 1, fn (a, b) { a > b }) }
194
+ a::global.filter(filter)
195
+ // # 转换日志
196
+ // - W: 使用了非精确转换的语法或函数,结果可能不准确
197
+ // # 原始 math.js 表达式
198
+ // filter(x) = x > 1; a.filter(filter)`,
199
+ [2, 3],
200
+ ],
201
+ [`print('hello world, $s!', {s:s})`, '`hello world, $(s)!`', `hello world, abc!`],
202
+ [`print('hello world, $1!', [s])`, '`hello world, $(s)!`', `hello world, abc!`],
203
+ [`concat('Value: ', f, string(1 >= 0))`, '`Value: $(f)$(1 >= 0)`', 'Value: 1true'],
204
+ [`concat(s, f, string(1 >= 0))`, '`$(s)$(f)$(1 >= 0)`', 'abc1true'],
205
+ [
206
+ String.raw`'Value: '.concat('\\x', '$', 1, f, string(1 >= 0))`,
207
+ '`Value: \\\\x\\$1$(f)$(1 >= 0)`',
208
+ String.raw`Value: \x$11true`,
209
+ ],
210
+ [
211
+ `concat([1], a)`,
212
+ dedent`
213
+ flatten([[1], a])
214
+ // # 转换日志
215
+ // - W: 矩阵连接时结果可能不一致
216
+ // # 原始 math.js 表达式
217
+ // concat([1], a)
218
+ `,
219
+ [1, 1, 2, 3],
220
+ ],
221
+ [`equalText(type, "keyword")`, `global.type == 'keyword'`, true],
222
+ [
223
+ `type = { "a": [1,2,3] }; type.a[1]`,
224
+ dedent`
225
+ let __type__ = (a: [1, 2, 3]);
226
+ return @@maybe_chars(__type__.a)[0];
227
+ // # 帮助函数
228
+ fn @@maybe_chars(x) { if type(x) == 'string' { chars(x) } else { x } }
229
+ // # 转换日志
230
+ // - W: 变量名 'type' 是 MiraScript 关键字,已转换为 '__type__'
231
+ // # 原始 math.js 表达式
232
+ // type = { "a": [1,2,3] }; type.a[1]
233
+ `,
234
+ 1,
235
+ ],
236
+ [
237
+ '[1,2,3].map(f(x,y,z) = x^2)',
238
+ dedent`
239
+ return [1, 2, 3]::map(f);
240
+ // # 帮助函数
241
+ fn f(x, y, z) { x^2 }
242
+ // # 转换日志
243
+ // - W: 使用了非精确转换的语法或函数,结果可能不准确
244
+ // - W: '^' 不支持矩阵,计算结果可能不一致
245
+ // # 原始 math.js 表达式
246
+ // [1,2,3].map(f(x,y,z) = x^2)
247
+ `,
248
+ [1, 4, 9],
249
+ ],
250
+ ['', '', null],
251
+ ['#', '//', null],
252
+ ['#xx', '//xx', null],
253
+ ['(random() - 1) < 0', '(random() - 1) < 0', true],
254
+ [
255
+ 're(12) + im(i)',
256
+ dedent`
257
+ /* re */(12) + /* im */(i)
258
+ // # 转换日志
259
+ // - E: 不支持复数
260
+ // # 原始 math.js 表达式
261
+ // re(12) + im(i)
262
+ `,
263
+ VmError,
264
+ ],
265
+ ['is(a, "number")', "type(a) == 'number'", false],
266
+ ['is(a, "string")', "type(a) == 'string'", false],
267
+ ['is(a, "boolean")', "type(a) == 'boolean'", false],
268
+ ['is(a, "null")', "type(a) == 'nil'", false],
269
+ ['is(a, "undefined")', "type(a) == 'nil'", false],
270
+ [`sum([a > 1])`, `sum([matrix.entrywise(a, 1, fn (a, b) { a > b })]::flatten())`, 2],
271
+ [`prod(1,2,3)`, `product(1, 2, 3)`, 6],
272
+ [`sum(true)`, `sum(true)`, 1],
273
+ [`sum(m)`, `sum(m::flatten())`, 10],
274
+ [`prod([1,2,3])`, `product([1, 2, 3])`, 6],
275
+ [`prod(f)`, `product(f)`, 1],
276
+ [`abs(f) + round(f) + f`, `abs(f) + round(f) + f`, 3],
277
+ [
278
+ `abs([1,2,3;-4,-5,-6])`,
279
+ `matrix.entrywise([[1, 2, 3], [-4, -5, -6]], nil, abs)`,
280
+ [
281
+ [1, 2, 3],
282
+ [4, 5, 6],
283
+ ],
284
+ ],
285
+ [`max(1, 2, f) + f`, `max(1, 2, f) + f`, 3],
286
+ [`min(1, 2, f) + f`, `min(1, 2, f) + f`, 2],
287
+ [
288
+ `max([1,2;3,4], 1)`,
289
+ dedent`
290
+ max([[1, 2], [3, 4]], 1)
291
+ // # 转换日志
292
+ // - W: 函数行为可能不一致: max
293
+ // # 原始 math.js 表达式
294
+ // max([1,2;3,4], 1)`,
295
+ VmError,
296
+ ],
297
+ [`0:(f + 1)`, `[0..(f + 1)]`, [0, 1, 2]],
298
+ [`3:1`, `[3..1]`, []],
299
+ [`1:+1:2`, `[1..2]`, [1, 2]],
300
+ [`3:-1:1`, `[1..3]`, [1, 2, 3]],
301
+ [`1:4 + 1`, `[1..4 + 1]`, [1, 2, 3, 4, 5]],
302
+ [`1.2:2*3`, `[1.2..2 * 3]`, [1.2, 2.2, 3.2, 4.2, 5.2]],
303
+ [`a[1:2]`, 'a[0..1]', [1, 2]],
304
+ [`a[2:-1:1]`, 'a[0..1]::reverse()', [2, 1]],
305
+ [`not b and f > 0`, `!b && f > 0`, true],
306
+ ])('should migrate expression: %s', (f, t, r) => {
307
+ const migrated = migrateMathJs(f as ExpressionSource, false, s);
308
+ expect(migrated).toBe(t);
309
+ if (typeof r === 'function' && r.prototype instanceof Error) {
310
+ expect(() => {
311
+ e.evaluate(Expression(migrated), s);
312
+ }).toThrow(r);
313
+ } else {
314
+ expect(e.evaluate(Expression(migrated), s)).toEqual(r);
315
+ }
316
+ });
317
+ });
package/tests/scope.ts CHANGED
@@ -10,7 +10,7 @@ describe('Scope should work correctly', () => {
10
10
  it('can create from function', () => {
11
11
  const s = new Scope((k) => (k === 'a' ? 12 : undefined), false);
12
12
  expect(e.evaluate(Expression('a'), s)).toBe(12);
13
- expect(e.evaluate(Expression('b'), s)).toBe(undefined);
13
+ expect(e.evaluate(Expression('`b` in global'), s)).toBe(false);
14
14
  });
15
15
  it('can create from object', () => {
16
16
  const s = new Scope({ a: 12, b: Expression('a + 1') }, false);
@@ -22,8 +22,8 @@ describe('Scope should work correctly', () => {
22
22
  describe('Scope should not leak dangerous objects', () => {
23
23
  it('should not access prototype fields', () => {
24
24
  const s = new Scope({}, false);
25
- expect(e.evaluate(Expression('__proto__'), s)).toBe(undefined);
26
- expect(e.evaluate(Expression('toString'), s)).toBe(undefined);
25
+ expect(e.evaluate(Expression('`__proto__` in global'), s)).toBe(false);
26
+ expect(e.evaluate(Expression('`toString` in global'), s)).toBe(false);
27
27
  });
28
28
  it('should access same name props', () => {
29
29
  const s = new Scope({ ['__proto__']: 12, toString: 'x' }, false);
@@ -0,0 +1,36 @@
1
+ import { Evaluator, Expression, Scope } from '../dist/index.js';
2
+
3
+ const e = new Evaluator();
4
+ const s = new Scope({}, false);
5
+
6
+ describe('Evaluator.template should work correctly', () => {
7
+ it('should eval null', () => {
8
+ const result = e.template(null, s);
9
+ expect(result).toBe('');
10
+ });
11
+ it('should eval undefined', () => {
12
+ const result = e.template(undefined, s);
13
+ expect(result).toBe('');
14
+ });
15
+ it('should eval empty', () => {
16
+ const result = e.template('', s);
17
+ expect(result).toBe('');
18
+ });
19
+ it('should eval const', () => {
20
+ const result = e.template('12', s);
21
+ expect(result).toBe('12');
22
+ });
23
+
24
+ it('should eval exp', () => {
25
+ const result = e.template('$(1 + 1)', s);
26
+ expect(result).toBe('2');
27
+ });
28
+ it('should eval error', () => {
29
+ const result = e.template('$(exp+++)', s);
30
+ expect(result).toBe('$(exp+++)');
31
+ });
32
+ it('should eval bad type', () => {
33
+ // @ts-expect-error 测试错误输入
34
+ expect(() => e.template(new Date(0), s)).toThrow(TypeError);
35
+ });
36
+ });
package/dist/context.d.ts DELETED
@@ -1,41 +0,0 @@
1
- import { LRUCache } from 'lru-cache';
2
- import type { ExpressionCache } from './parser.js';
3
- import type { VmValue } from '@mirascript/mirascript';
4
- /** 日志 */
5
- export interface Logger {
6
- /**
7
- * error
8
- */
9
- error(...args: unknown[]): void;
10
- /**
11
- * warning
12
- */
13
- warn(...args: unknown[]): void;
14
- /**
15
- * info
16
- */
17
- info(...args: unknown[]): void;
18
- /**
19
- * debug
20
- */
21
- debug(...args: unknown[]): void;
22
- }
23
- /** 选项 */
24
- export interface Options {
25
- /** 日志 */
26
- logger: Logger;
27
- /** 表达式缓存 */
28
- expressionCacheSize: number;
29
- }
30
- /** 执行上下文 */
31
- export declare class Context {
32
- constructor(options?: Partial<Options>);
33
- readonly imported: Map<string, VmValue>;
34
- /** Logger */
35
- get logger(): Logger;
36
- /** 选项 */
37
- readonly options: Options;
38
- /** 表达式缓存 */
39
- readonly expressionCache: LRUCache<string, ExpressionCache, unknown>;
40
- }
41
- //# sourceMappingURL=context.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEtD,SAAS;AACT,MAAM,WAAW,MAAM;IACnB;;OAEG;IACH,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChC;;OAEG;IACH,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC/B;;OAEG;IACH,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC/B;;OAEG;IACH,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CACnC;AAED,SAAS;AACT,MAAM,WAAW,OAAO;IACpB,SAAS;IACT,MAAM,EAAE,MAAM,CAAC;IACf,YAAY;IACZ,mBAAmB,EAAE,MAAM,CAAC;CAC/B;AAOD,YAAY;AACZ,qBAAa,OAAO;gBACJ,OAAO,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC;IAItC,QAAQ,CAAC,QAAQ,uBAA8B;IAC/C,aAAa;IACb,IAAI,MAAM,IAAI,MAAM,CAEnB;IACD,SAAS;IACT,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAE1B,YAAY;IACZ,QAAQ,CAAC,eAAe,6CAAC;CAC5B"}
package/dist/context.js DELETED
@@ -1,18 +0,0 @@
1
- import { LRUCache } from 'lru-cache';
2
- const defaultOptions = {
3
- logger: console,
4
- expressionCacheSize: 50,
5
- };
6
- /** 执行上下文 */
7
- export class Context {
8
- constructor(options) {
9
- this.imported = new Map();
10
- this.options = { ...options, ...defaultOptions };
11
- this.expressionCache = new LRUCache({ max: this.options.expressionCacheSize });
12
- }
13
- /** Logger */
14
- get logger() {
15
- return this.options.logger ?? console;
16
- }
17
- }
18
- //# sourceMappingURL=context.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAgCrC,MAAM,cAAc,GAAY;IAC5B,MAAM,EAAE,OAAO;IACf,mBAAmB,EAAE,EAAE;CAC1B,CAAC;AAEF,YAAY;AACZ,MAAM,OAAO,OAAO;IAChB,YAAY,OAA0B;QAI7B,aAAQ,GAAG,IAAI,GAAG,EAAmB,CAAC;QAH3C,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;QACjD,IAAI,CAAC,eAAe,GAAG,IAAI,QAAQ,CAA0B,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAC5G,CAAC;IAED,aAAa;IACb,IAAI,MAAM;QACN,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC;IAC1C,CAAC;CAMJ"}
package/src/context.ts DELETED
@@ -1,54 +0,0 @@
1
- import { LRUCache } from 'lru-cache';
2
- import type { ExpressionCache } from './parser.js';
3
- import type { VmValue } from '@mirascript/mirascript';
4
-
5
- /** 日志 */
6
- export interface Logger {
7
- /**
8
- * error
9
- */
10
- error(...args: unknown[]): void;
11
- /**
12
- * warning
13
- */
14
- warn(...args: unknown[]): void;
15
- /**
16
- * info
17
- */
18
- info(...args: unknown[]): void;
19
- /**
20
- * debug
21
- */
22
- debug(...args: unknown[]): void;
23
- }
24
-
25
- /** 选项 */
26
- export interface Options {
27
- /** 日志 */
28
- logger: Logger;
29
- /** 表达式缓存 */
30
- expressionCacheSize: number;
31
- }
32
-
33
- const defaultOptions: Options = {
34
- logger: console,
35
- expressionCacheSize: 50,
36
- };
37
-
38
- /** 执行上下文 */
39
- export class Context {
40
- constructor(options?: Partial<Options>) {
41
- this.options = { ...options, ...defaultOptions };
42
- this.expressionCache = new LRUCache<string, ExpressionCache>({ max: this.options.expressionCacheSize });
43
- }
44
- readonly imported = new Map<string, VmValue>();
45
- /** Logger */
46
- get logger(): Logger {
47
- return this.options.logger ?? console;
48
- }
49
- /** 选项 */
50
- readonly options: Options;
51
-
52
- /** 表达式缓存 */
53
- readonly expressionCache;
54
- }