@cloudpss/expression 0.6.0-alpha.2 → 0.6.0-alpha.20

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 (169) hide show
  1. package/dist/analyze.d.ts +6 -3
  2. package/dist/analyze.d.ts.map +1 -1
  3. package/dist/analyze.js +67 -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-decoration.d.ts +3 -3
  12. package/dist/definitions/parameter-decoration.d.ts.map +1 -1
  13. package/dist/definitions/parameter-decoration.js +0 -7
  14. package/dist/definitions/parameter-decoration.js.map +1 -1
  15. package/dist/definitions/parameter-group.d.ts +0 -4
  16. package/dist/definitions/parameter-group.d.ts.map +1 -1
  17. package/dist/definitions/parameter-group.js +5 -17
  18. package/dist/definitions/parameter-group.js.map +1 -1
  19. package/dist/definitions/parameter.d.ts +47 -40
  20. package/dist/definitions/parameter.d.ts.map +1 -1
  21. package/dist/definitions/parameter.js +9 -21
  22. package/dist/definitions/parameter.js.map +1 -1
  23. package/dist/definitions/utils.d.ts +28 -0
  24. package/dist/definitions/utils.d.ts.map +1 -0
  25. package/dist/definitions/utils.js +209 -0
  26. package/dist/definitions/utils.js.map +1 -0
  27. package/dist/definitions/variable.d.ts +0 -2
  28. package/dist/definitions/variable.d.ts.map +1 -1
  29. package/dist/definitions/variable.js +1 -5
  30. package/dist/definitions/variable.js.map +1 -1
  31. package/dist/definitions.d.ts +1 -0
  32. package/dist/definitions.d.ts.map +1 -1
  33. package/dist/definitions.js +1 -0
  34. package/dist/definitions.js.map +1 -1
  35. package/dist/eval.d.ts +3 -5
  36. package/dist/eval.d.ts.map +1 -1
  37. package/dist/eval.js +12 -20
  38. package/dist/eval.js.map +1 -1
  39. package/dist/expression.d.ts +10 -4
  40. package/dist/expression.d.ts.map +1 -1
  41. package/dist/expression.js +6 -6
  42. package/dist/expression.js.map +1 -1
  43. package/dist/index.d.ts +3 -1
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +1 -0
  46. package/dist/index.js.map +1 -1
  47. package/dist/interface.d.ts +30 -0
  48. package/dist/interface.d.ts.map +1 -0
  49. package/dist/interface.js +6 -0
  50. package/dist/interface.js.map +1 -0
  51. package/dist/main.d.ts +41 -28
  52. package/dist/main.d.ts.map +1 -1
  53. package/dist/main.js +149 -147
  54. package/dist/main.js.map +1 -1
  55. package/dist/migrate.d.ts +3 -2
  56. package/dist/migrate.d.ts.map +1 -1
  57. package/dist/migrate.js +25 -3
  58. package/dist/migrate.js.map +1 -1
  59. package/dist/migrator/access.d.ts.map +1 -1
  60. package/dist/migrator/access.js +45 -25
  61. package/dist/migrator/access.js.map +1 -1
  62. package/dist/migrator/call.d.ts.map +1 -1
  63. package/dist/migrator/call.js +298 -201
  64. package/dist/migrator/call.js.map +1 -1
  65. package/dist/migrator/concat.d.ts.map +1 -1
  66. package/dist/migrator/concat.js +15 -2
  67. package/dist/migrator/concat.js.map +1 -1
  68. package/dist/migrator/function.d.ts +6 -0
  69. package/dist/migrator/function.d.ts.map +1 -0
  70. package/dist/migrator/function.js +25 -0
  71. package/dist/migrator/function.js.map +1 -0
  72. package/dist/migrator/interface.d.ts +3 -1
  73. package/dist/migrator/interface.d.ts.map +1 -1
  74. package/dist/migrator/interface.js.map +1 -1
  75. package/dist/migrator/node.d.ts.map +1 -1
  76. package/dist/migrator/node.js +35 -6
  77. package/dist/migrator/node.js.map +1 -1
  78. package/dist/migrator/operator.d.ts.map +1 -1
  79. package/dist/migrator/operator.js +107 -60
  80. package/dist/migrator/operator.js.map +1 -1
  81. package/dist/migrator/serialize.d.ts +4 -0
  82. package/dist/migrator/serialize.d.ts.map +1 -0
  83. package/dist/migrator/serialize.js +21 -0
  84. package/dist/migrator/serialize.js.map +1 -0
  85. package/dist/migrator/special.d.ts.map +1 -1
  86. package/dist/migrator/special.js +31 -0
  87. package/dist/migrator/special.js.map +1 -1
  88. package/dist/migrator/state.d.ts +2 -2
  89. package/dist/migrator/state.d.ts.map +1 -1
  90. package/dist/migrator/state.js +30 -33
  91. package/dist/migrator/state.js.map +1 -1
  92. package/dist/migrator/symbol.d.ts.map +1 -1
  93. package/dist/migrator/symbol.js +23 -9
  94. package/dist/migrator/symbol.js.map +1 -1
  95. package/dist/migrator/to-type.d.ts.map +1 -1
  96. package/dist/migrator/to-type.js +21 -4
  97. package/dist/migrator/to-type.js.map +1 -1
  98. package/dist/migrator/utils.d.ts +6 -0
  99. package/dist/migrator/utils.d.ts.map +1 -1
  100. package/dist/migrator/utils.js +35 -0
  101. package/dist/migrator/utils.js.map +1 -1
  102. package/dist/parser.d.ts +2 -2
  103. package/dist/parser.d.ts.map +1 -1
  104. package/dist/parser.js +27 -8
  105. package/dist/parser.js.map +1 -1
  106. package/dist/re-exports.d.ts +4 -0
  107. package/dist/re-exports.d.ts.map +1 -0
  108. package/dist/re-exports.js +3 -0
  109. package/dist/re-exports.js.map +1 -0
  110. package/dist/scope.d.ts +17 -18
  111. package/dist/scope.d.ts.map +1 -1
  112. package/dist/scope.js +84 -53
  113. package/dist/scope.js.map +1 -1
  114. package/dist/type.d.ts +27 -6
  115. package/dist/type.d.ts.map +1 -1
  116. package/dist/type.js +34 -15
  117. package/dist/type.js.map +1 -1
  118. package/package.json +8 -5
  119. package/src/analyze.ts +77 -37
  120. package/src/definitions/argument.ts +3 -13
  121. package/src/definitions/constraint.ts +3 -3
  122. package/src/definitions/parameter-decoration.ts +3 -9
  123. package/src/definitions/parameter-group.ts +4 -19
  124. package/src/definitions/parameter.ts +70 -62
  125. package/src/definitions/utils.ts +224 -0
  126. package/src/definitions/variable.ts +1 -6
  127. package/src/definitions.ts +1 -0
  128. package/src/eval.ts +16 -25
  129. package/src/expression.ts +16 -8
  130. package/src/index.ts +3 -1
  131. package/src/interface.ts +35 -0
  132. package/src/main.ts +217 -199
  133. package/src/migrate.ts +30 -6
  134. package/src/migrator/access.ts +50 -33
  135. package/src/migrator/call.ts +287 -190
  136. package/src/migrator/concat.ts +15 -2
  137. package/src/migrator/function.ts +27 -0
  138. package/src/migrator/interface.ts +3 -1
  139. package/src/migrator/node.ts +36 -5
  140. package/src/migrator/operator.ts +110 -64
  141. package/src/migrator/serialize.ts +21 -0
  142. package/src/migrator/special.ts +31 -0
  143. package/src/migrator/state.ts +30 -33
  144. package/src/migrator/symbol.ts +23 -9
  145. package/src/migrator/to-type.ts +23 -4
  146. package/src/migrator/utils.ts +38 -0
  147. package/src/parser.ts +33 -8
  148. package/src/re-exports.ts +47 -0
  149. package/src/scope.ts +101 -65
  150. package/src/type.ts +52 -18
  151. package/tests/analyze.ts +40 -6
  152. package/tests/compile.ts +65 -0
  153. package/tests/condition.ts +33 -17
  154. package/tests/definition.ts +237 -18
  155. package/tests/eval-complex.ts +19 -11
  156. package/tests/eval.ts +59 -12
  157. package/tests/import.ts +21 -7
  158. package/tests/main.ts +58 -0
  159. package/tests/migrate.ts +308 -0
  160. package/tests/scope.ts +3 -3
  161. package/tests/template.ts +36 -0
  162. package/dist/context.d.ts +0 -41
  163. package/dist/context.d.ts.map +0 -1
  164. package/dist/context.js +0 -18
  165. package/dist/context.js.map +0 -1
  166. package/jest.config.js +0 -3
  167. package/src/context.ts +0 -54
  168. package/tests/tsconfig.json +0 -3
  169. package/tsconfig.json +0 -3
package/tests/analyze.ts CHANGED
@@ -1,15 +1,49 @@
1
1
  import { Evaluator, Expression, Scope } from '../dist/index.js';
2
2
 
3
3
  const e = new Evaluator();
4
- const s = new Scope({}, false);
4
+ e.import({ w: 123 });
5
+ const s = new Scope({ sin: 12 }, false);
5
6
 
6
- describe.skip('Analyze', () => {
7
+ describe('Analyze', () => {
7
8
  it('simple', () => {
8
- expect(e.analyze(Expression('a+b'), s)).toEqual([['a'], ['b']]);
9
+ expect(e.analyze(Expression(' '), s)).toEqual([]);
10
+ expect(e.analyze(Expression('a + b + @c'), s)).toEqual([['a'], ['b'], ['@c']]);
11
+ });
12
+ it('bad', () => {
13
+ expect(e.analyze(Expression('a + '), s)).toEqual([]);
14
+ expect(e.analyze(Expression('a.b.'), s)).toEqual([]);
15
+ expect(() => e.analyze(Expression('a.b.'))).toThrow();
16
+ });
17
+ it('local', () => {
18
+ expect(e.analyze(Expression('let a = 12; a + nil'), s)).toEqual([]);
19
+ expect(e.analyze(Expression('let a = 12; a + nil'), s)).toEqual([]);
20
+ expect(e.analyze(Expression('let a = 12; a + b'), s)).toEqual([['b']]);
21
+ });
22
+ it('repeat', () => {
23
+ expect(e.analyze(Expression('a + b + a + a.b + b.c + a * a !. b'), s)).toEqual([
24
+ ['a'],
25
+ ['b'],
26
+ ['a', 'b'],
27
+ ['b', 'c'],
28
+ ]);
29
+ });
30
+ it('prefixed', () => {
31
+ expect(e.analyze(Expression('@@a + $b + c. $$ + $'), s)).toEqual([['@@a'], ['$b'], ['c', '$$'], ['$']]);
32
+ });
33
+ it('unicode', () => {
34
+ expect(e.analyze(Expression('变量.属性 + 变量2[索引] + 函数()'), s)).toEqual([]);
9
35
  });
10
36
  it('access', () => {
11
- expect(e.analyze(Expression('a.b[1]+b'), s)).toEqual([['a', 'b'], ['b']]);
12
- expect(e.analyze(Expression('a.b["x"]+b'), s)).toEqual([['a', 'b', 'x'], ['b']]);
13
- expect(e.analyze(Expression('a.b[x]+b'), s)).toEqual([['a', 'b'], ['x'], ['b']]);
37
+ expect(e.analyze(Expression('a .b [1]+b'), s)).toEqual([['a', 'b'], ['b']]);
38
+ expect(e.analyze(Expression('a. b["x"]+b'), s)).toEqual([['a', 'b'], ['b']]);
39
+ expect(e.analyze(Expression('a.b[x] + b + c.12.3'), s)).toEqual([['a', 'b'], ['x'], ['b'], ['c', 12, 3]]);
40
+ });
41
+ it('with lib', () => {
42
+ const e0 = new Evaluator();
43
+ const exp = Expression('sin(x) + y::z.t()::cos() + w.123');
44
+ expect(e.analyze(exp, s)).toEqual([['sin'], ['x'], ['z', 't'], ['y']]);
45
+ expect(e0.analyze(exp, s)).toEqual([['sin'], ['x'], ['z', 't'], ['y'], ['w', 123]]);
46
+ expect(e.analyze(exp)).toEqual([['x'], ['z', 't'], ['y']]);
47
+ expect(e0.analyze(exp)).toEqual([['x'], ['z', 't'], ['y'], ['w', 123]]);
14
48
  });
15
49
  });
@@ -0,0 +1,65 @@
1
+ import { Evaluator, Expression, Scope } from '../dist/index.js';
2
+
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
+ });
11
+ const s = new Scope({}, false);
12
+
13
+ describe('Evaluator.compile should work correctly', () => {
14
+ it('should eval const', () => {
15
+ const result = e.compile(Expression('12'), false);
16
+ expect(result(s, e)).toBe(12);
17
+ expect(e.evaluate(result, s)).toBe(12);
18
+ });
19
+
20
+ it('should eval exp', () => {
21
+ const result = e.compile(Expression('exp(2)'), false);
22
+ expect(result(s, e)).toBe(Math.exp(2));
23
+ expect(e.evaluate(result, s)).toBe(Math.exp(2));
24
+ });
25
+
26
+ it('should eval error', () => {
27
+ const result = e.compile(Expression('exp+++'), false);
28
+ expect(result(s, e)).toBe(null);
29
+ expect(e.evaluate(result, s)).toBe(null);
30
+ });
31
+ });
32
+
33
+ describe('Evaluator.compile should convert result', () => {
34
+ it('should eval const', () => {
35
+ const result = e.compile(Expression('12', 'string'), false);
36
+ expect(result(s, e)).toBe('12');
37
+ expect(e.evaluate(result, s)).toBe('12');
38
+ });
39
+
40
+ it('should eval exp', () => {
41
+ const result = e.compile(Expression('exp(2)', 's'), false);
42
+ expect(result(s, e)).toBe(Math.exp(2).toString());
43
+ expect(e.evaluate(result, s)).toBe(Math.exp(2).toString());
44
+ });
45
+
46
+ it('should not convert defaults', () => {
47
+ {
48
+ const result = e.compile(Expression('nil', 's'), false);
49
+ expect(result(s, e)).toBe(null);
50
+ expect(e.evaluate(result, s, 1)).toBe(1);
51
+ }
52
+ {
53
+ // syntax error
54
+ const result = e.compile(Expression('exp+++', 's'), false);
55
+ expect(result(s, e)).toBe(null);
56
+ expect(e.evaluate(result, s, 1)).toBe(1);
57
+ }
58
+ {
59
+ // runtime error
60
+ const result = e.compile(Expression('x() + 1', 's'), false);
61
+ expect(result(s, e)).toBe(null);
62
+ expect(e.evaluate(result, s, 1)).toBe(1);
63
+ }
64
+ });
65
+ });
@@ -1,6 +1,16 @@
1
1
  import { Evaluator, type ExpressionSource, Scope } from '../dist/index.js';
2
2
 
3
- const e = new Evaluator();
3
+ const e = new Evaluator({
4
+ logger: undefined,
5
+ });
6
+ const en = new Evaluator({
7
+ logger: {
8
+ warn: () => void 0,
9
+ error: () => void 0,
10
+ info: () => void 0,
11
+ debug: () => void 0,
12
+ },
13
+ });
4
14
  const s = new Scope(undefined, false);
5
15
 
6
16
  describe('Evaluate conditions', () => {
@@ -9,7 +19,6 @@ describe('Evaluate conditions', () => {
9
19
  expect(e.evaluateCondition(false, s)).toBe(false);
10
20
  });
11
21
  it('can evaluate empty literals', () => {
12
- // @ts-expect-error null
13
22
  expect(e.evaluateCondition(null, s)).toBe(true);
14
23
  expect(e.evaluateCondition(undefined, s)).toBe(true);
15
24
  });
@@ -18,20 +27,28 @@ describe('Evaluate conditions', () => {
18
27
  expect(e.evaluateCondition('true' as ExpressionSource<boolean>, s)).toBe(true);
19
28
  expect(e.evaluateCondition('false' as ExpressionSource<boolean>, s)).toBe(false);
20
29
  });
21
- it('can convert to boolean', () => {
22
- expect(e.evaluateCondition('""' as ExpressionSource<boolean>, s)).toBe(true);
23
- expect(e.evaluateCondition('nil' as ExpressionSource<boolean>, s)).toBe(true);
24
- expect(e.evaluateCondition('undefined' as ExpressionSource<boolean>, s)).toBe(true);
25
- expect(e.evaluateCondition('0' as ExpressionSource<boolean>, s)).toBe(true);
26
- expect(e.evaluateCondition('nan' as ExpressionSource<boolean>, s)).toBe(true);
30
+ it('can evaluate to boolean', () => {
27
31
  expect(e.evaluateCondition('(false)' as ExpressionSource<boolean>, s)).toBe(false);
28
-
29
- expect(e.evaluateCondition('""' as ExpressionSource<boolean>, s, false)).toBe(true);
30
- expect(e.evaluateCondition('nil' as ExpressionSource<boolean>, s, false)).toBe(false);
31
- expect(e.evaluateCondition('undefined' as ExpressionSource<boolean>, s, false)).toBe(false);
32
- expect(e.evaluateCondition('0' as ExpressionSource<boolean>, s, false)).toBe(true);
33
- expect(e.evaluateCondition('nan' as ExpressionSource<boolean>, s, false)).toBe(true);
32
+ expect(e.evaluateCondition('(true)' as ExpressionSource<boolean>, s)).toBe(true);
34
33
  expect(e.evaluateCondition('(false)' as ExpressionSource<boolean>, s, false)).toBe(false);
34
+ expect(e.evaluateCondition('(true)' as ExpressionSource<boolean>, s, false)).toBe(true);
35
+ });
36
+ it('can evaluate to nil', () => {
37
+ expect(e.evaluateCondition('{}' as ExpressionSource<boolean>, s)).toBe(true);
38
+ expect(e.evaluateCondition('{}' as ExpressionSource<boolean>, s, false)).toBe(false);
39
+ });
40
+ it('do not convert to boolean', () => {
41
+ expect(en.evaluateCondition('""' as ExpressionSource<boolean>, s)).toBe(true);
42
+ expect(en.evaluateCondition('nil' as ExpressionSource<boolean>, s)).toBe(true);
43
+ expect(en.evaluateCondition('undefined' as ExpressionSource<boolean>, s)).toBe(true);
44
+ expect(en.evaluateCondition('0' as ExpressionSource<boolean>, s)).toBe(true);
45
+ expect(en.evaluateCondition('nan' as ExpressionSource<boolean>, s)).toBe(true);
46
+
47
+ expect(en.evaluateCondition('""' as ExpressionSource<boolean>, s, false)).toBe(false);
48
+ expect(en.evaluateCondition('nil' as ExpressionSource<boolean>, s, false)).toBe(false);
49
+ expect(en.evaluateCondition('undefined' as ExpressionSource<boolean>, s, false)).toBe(false);
50
+ expect(en.evaluateCondition('0' as ExpressionSource<boolean>, s, false)).toBe(false);
51
+ expect(en.evaluateCondition('nan' as ExpressionSource<boolean>, s, false)).toBe(false);
35
52
  });
36
53
  it('can evaluate complex', () => {
37
54
  expect(e.evaluateCondition('12>3' as ExpressionSource<boolean>, s)).toBe(true);
@@ -42,8 +59,7 @@ describe('Evaluate conditions', () => {
42
59
  expect(e.evaluateCondition('12<=3' as ExpressionSource<boolean>, s)).toBe(false);
43
60
  });
44
61
  it('can return default on error', () => {
45
- expect(e.evaluateCondition('12>>3' as ExpressionSource<boolean>, undefined, true)).toBe(true);
46
- // @ts-expect-error null
47
- expect(e.evaluateCondition('12>>3' as ExpressionSource<boolean>, null, false)).toBe(false);
62
+ expect(en.evaluateCondition('12>>3' as ExpressionSource<boolean>, undefined, true)).toBe(true);
63
+ expect(en.evaluateCondition('12>>3' as ExpressionSource<boolean>, null, false)).toBe(false);
48
64
  });
49
65
  });
@@ -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.Parameter()).toBeDefined();
6
- expect(def.isParameter(def.Parameter())).toBe(true);
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.ParameterGroup()).toBeDefined();
11
- expect(def.isParameterGroup(def.ParameterGroup())).toBe(true);
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.ParameterDecoration()).toBeDefined();
16
- expect(def.isParameterDecoration(def.ParameterDecoration())).toBe(true);
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.ParameterDecorationGroup()).toBeDefined();
21
- expect(def.isParameterDecorationGroup(def.ParameterDecorationGroup())).toBe(true);
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.Variable()).toBeDefined();
26
- expect(def.isVariable(def.Variable())).toBe(true);
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.Choice()).toBeDefined();
31
- expect(def.isChoice(def.Choice())).toBe(true);
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
- expect(def.Choice('x').key).toBe('x');
34
- expect(def.isChoice(def.Choice('x'))).toBe(true);
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
- expect(def.Choice(0).key).toBe(0);
37
- expect(def.isChoice(def.Choice(0))).toBe(true);
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(def.Choice(false).key).toBe(false);
40
- expect(def.isChoice(def.Choice(false))).toBe(true);
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
  });
@@ -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('b.0 + d.0')]),
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).toBe(36);
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)).toBe(3);
148
- expect(e.evaluate(Expression('o.z'), s)).toBe(3);
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(undefined);
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 when error', () => {
35
- // syntax error
36
- const result = e.evaluate(Expression('exp+++', 's'), s, 1);
37
- expect(result).toBe(1);
38
- // runtime error
39
- const result2 = e.evaluate(Expression('x() + 1', 's'), s, 1);
40
- expect(result2).toBe(1);
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
  });