sval 0.4.8 → 0.5.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.
- package/.github/workflows/coverage.yml +21 -0
- package/README.md +8 -9
- package/dist/sval.es6.js +89 -14
- package/dist/sval.js +132 -42
- package/dist/sval.min.js +1 -1
- package/package.json +5 -7
- package/types/index.d.ts +3 -2
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: Coverage
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches:
|
|
5
|
+
- master
|
|
6
|
+
jobs:
|
|
7
|
+
coverage:
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
steps:
|
|
10
|
+
- name: Check out repository code
|
|
11
|
+
uses: actions/checkout@v3
|
|
12
|
+
- name: Setup node environment
|
|
13
|
+
uses: actions/setup-node@v3.4.1
|
|
14
|
+
- name: Install node modules
|
|
15
|
+
run: npm install
|
|
16
|
+
- name: Test code
|
|
17
|
+
run: npm test
|
|
18
|
+
- name: Send coverage info to Coveralls
|
|
19
|
+
uses: coverallsapp/github-action@1.1.3
|
|
20
|
+
with:
|
|
21
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
package/README.md
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
# Sval
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/sval)
|
|
4
|
-
[](https://travis-ci.org/Siubaak/sval)
|
|
5
|
-
[](https://coveralls.io/github/Siubaak/sval)
|
|
1
|
+
# Sval · [](https://www.npmjs.com/package/sval) [](https://github.com/Siubaak/sval/actions/workflows/coverage.yml) [](https://coveralls.io/github/Siubaak/sval)
|
|
6
2
|
|
|
7
3
|
A JavaScript interpreter writen in JavaScript, based on parser [Acorn](https://github.com/acornjs/acorn).
|
|
8
4
|
|
|
@@ -38,8 +34,11 @@ import Sval from 'sval'
|
|
|
38
34
|
|
|
39
35
|
// Sval options
|
|
40
36
|
const options = {
|
|
41
|
-
// ECMA Version of the code
|
|
42
|
-
|
|
37
|
+
// ECMA Version of the code
|
|
38
|
+
// 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15
|
|
39
|
+
// or 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024
|
|
40
|
+
// or "latest"
|
|
41
|
+
ecmaVer: 'latest',
|
|
43
42
|
// Whether the code runs in a sandbox
|
|
44
43
|
sandBox: true,
|
|
45
44
|
}
|
|
@@ -68,11 +67,11 @@ console.log(interpreter.exports.mod) // Get 'AllKindsOfStuffs'
|
|
|
68
67
|
|
|
69
68
|
Sval constructor has options with two fields, **ecmaVer** and **sandBox**.
|
|
70
69
|
|
|
71
|
-
- **ecmaVer** is the ECMAScript edition of the code. Currently, 5, 6(2015), 7(2016), 8(2017), 9(2018)
|
|
70
|
+
- **ecmaVer** is the ECMAScript edition of the code. Currently, 3, 5, 6(2015), 7(2016), 8(2017), 9(2018), 10(2019), 11(2020), 12(2021), 13(2022), 14(2023), 15(2024) and "latest" are supported, and the default edition is "latest".
|
|
72
71
|
|
|
73
72
|
- **sandBox** is true for sandbox mode or false for invasived mode. Sandbox mode will run code in an isolated sandbox and won't pollute your global scope. Invasived mode allows you run code in the same global scope of your current environment. The default setting is true.
|
|
74
73
|
|
|
75
|
-
Sval instance has
|
|
74
|
+
Sval instance has three methods, **import**, **parse** and **run**.
|
|
76
75
|
|
|
77
76
|
- **import** is to import modules into your Sval instance scope, expecting a name and a module as arguments like `import(name: string, mod: any)`, or an object which contains the modules as argument like `import({ [name: string]: any })`. The modules will be automatically declared as global variables. This method is more likely to be used in sandbox mode.
|
|
78
77
|
|
package/dist/sval.es6.js
CHANGED
|
@@ -383,7 +383,7 @@
|
|
|
383
383
|
}
|
|
384
384
|
}
|
|
385
385
|
|
|
386
|
-
var version = "0.
|
|
386
|
+
var version = "0.5.0";
|
|
387
387
|
|
|
388
388
|
const AWAIT = { RES: undefined };
|
|
389
389
|
const RETURN = { RES: undefined };
|
|
@@ -733,7 +733,7 @@
|
|
|
733
733
|
}
|
|
734
734
|
}
|
|
735
735
|
function AssignmentExpression(node, scope) {
|
|
736
|
-
|
|
736
|
+
var _a;
|
|
737
737
|
const left = node.left;
|
|
738
738
|
let variable;
|
|
739
739
|
if (left.type === 'Identifier') {
|
|
@@ -747,8 +747,10 @@
|
|
|
747
747
|
variable = MemberExpression(left, scope, { getVar: true });
|
|
748
748
|
}
|
|
749
749
|
else {
|
|
750
|
+
const value = evaluate(node.right, scope);
|
|
750
751
|
return pattern$3(left, scope, { feed: value });
|
|
751
752
|
}
|
|
753
|
+
const value = evaluate(node.right, scope);
|
|
752
754
|
switch (node.operator) {
|
|
753
755
|
case '=':
|
|
754
756
|
variable.set(value);
|
|
@@ -789,15 +791,27 @@
|
|
|
789
791
|
case '&=':
|
|
790
792
|
variable.set(variable.get() & value);
|
|
791
793
|
return variable.get();
|
|
794
|
+
case '??=':
|
|
795
|
+
variable.set((_a = variable.get()) !== null && _a !== void 0 ? _a : value);
|
|
796
|
+
return variable.get();
|
|
797
|
+
case '&&=':
|
|
798
|
+
variable.set(variable.get() && value);
|
|
799
|
+
return variable.get();
|
|
800
|
+
case '||=':
|
|
801
|
+
variable.set(variable.get() || value);
|
|
802
|
+
return variable.get();
|
|
792
803
|
default: throw new SyntaxError(`Unexpected token ${node.operator}`);
|
|
793
804
|
}
|
|
794
805
|
}
|
|
795
806
|
function LogicalExpression(node, scope) {
|
|
807
|
+
var _a;
|
|
796
808
|
switch (node.operator) {
|
|
797
809
|
case '||':
|
|
798
810
|
return (evaluate(node.left, scope)) || (evaluate(node.right, scope));
|
|
799
811
|
case '&&':
|
|
800
812
|
return (evaluate(node.left, scope)) && (evaluate(node.right, scope));
|
|
813
|
+
case '??':
|
|
814
|
+
return (_a = (evaluate(node.left, scope))) !== null && _a !== void 0 ? _a : (evaluate(node.right, scope));
|
|
801
815
|
default:
|
|
802
816
|
throw new SyntaxError(`Unexpected token ${node.operator}`);
|
|
803
817
|
}
|
|
@@ -836,9 +850,15 @@
|
|
|
836
850
|
const getter = getGetter(object, key);
|
|
837
851
|
if (node.object.type === 'Super' && getter) {
|
|
838
852
|
const thisObject = scope.find('this').get();
|
|
853
|
+
if (node.optional && thisObject == null) {
|
|
854
|
+
return undefined;
|
|
855
|
+
}
|
|
839
856
|
return getter.call(thisObject);
|
|
840
857
|
}
|
|
841
858
|
else {
|
|
859
|
+
if (node.optional && object == null) {
|
|
860
|
+
return undefined;
|
|
861
|
+
}
|
|
842
862
|
return object[key];
|
|
843
863
|
}
|
|
844
864
|
}
|
|
@@ -853,6 +873,9 @@
|
|
|
853
873
|
let object;
|
|
854
874
|
if (node.callee.type === 'MemberExpression') {
|
|
855
875
|
object = MemberExpression(node.callee, scope, { getObj: true });
|
|
876
|
+
if (node.callee.optional && object == null) {
|
|
877
|
+
return undefined;
|
|
878
|
+
}
|
|
856
879
|
let key;
|
|
857
880
|
if (node.callee.computed) {
|
|
858
881
|
key = evaluate(node.callee.property, scope);
|
|
@@ -867,6 +890,9 @@
|
|
|
867
890
|
else {
|
|
868
891
|
func = object[key];
|
|
869
892
|
}
|
|
893
|
+
if (node.optional && func == null) {
|
|
894
|
+
return undefined;
|
|
895
|
+
}
|
|
870
896
|
if (typeof func !== 'function') {
|
|
871
897
|
throw new TypeError(`${key} is not a function`);
|
|
872
898
|
}
|
|
@@ -877,6 +903,9 @@
|
|
|
877
903
|
else {
|
|
878
904
|
object = scope.find('this').get();
|
|
879
905
|
func = evaluate(node.callee, scope);
|
|
906
|
+
if (node.optional && func == null) {
|
|
907
|
+
return undefined;
|
|
908
|
+
}
|
|
880
909
|
if (typeof func !== 'function' || node.callee.type !== 'Super' && func[CLSCTOR]) {
|
|
881
910
|
let name;
|
|
882
911
|
if (node.callee.type === 'Identifier') {
|
|
@@ -1020,6 +1049,9 @@
|
|
|
1020
1049
|
}
|
|
1021
1050
|
function SpreadElement(node, scope) {
|
|
1022
1051
|
return evaluate(node.argument, scope);
|
|
1052
|
+
}
|
|
1053
|
+
function ChainExpression(node, scope) {
|
|
1054
|
+
return evaluate(node.expression, scope);
|
|
1023
1055
|
}
|
|
1024
1056
|
|
|
1025
1057
|
var expression = /*#__PURE__*/Object.freeze({
|
|
@@ -1045,7 +1077,8 @@
|
|
|
1045
1077
|
TemplateElement: TemplateElement,
|
|
1046
1078
|
ClassExpression: ClassExpression,
|
|
1047
1079
|
Super: Super,
|
|
1048
|
-
SpreadElement: SpreadElement
|
|
1080
|
+
SpreadElement: SpreadElement,
|
|
1081
|
+
ChainExpression: ChainExpression
|
|
1049
1082
|
});
|
|
1050
1083
|
|
|
1051
1084
|
function ExpressionStatement(node, scope) {
|
|
@@ -1474,7 +1507,10 @@
|
|
|
1474
1507
|
function ClassBody(node, scope, options = {}) {
|
|
1475
1508
|
const { klass, superClass } = options;
|
|
1476
1509
|
for (let i = 0; i < node.body.length; i++) {
|
|
1477
|
-
|
|
1510
|
+
const def = node.body[i];
|
|
1511
|
+
if (def.type === 'MethodDefinition') {
|
|
1512
|
+
MethodDefinition(def, scope, { klass, superClass });
|
|
1513
|
+
}
|
|
1478
1514
|
}
|
|
1479
1515
|
}
|
|
1480
1516
|
function MethodDefinition(node, scope, options = {}) {
|
|
@@ -1733,7 +1769,7 @@
|
|
|
1733
1769
|
}
|
|
1734
1770
|
}
|
|
1735
1771
|
function* AssignmentExpression$1(node, scope) {
|
|
1736
|
-
|
|
1772
|
+
var _a;
|
|
1737
1773
|
const left = node.left;
|
|
1738
1774
|
let variable;
|
|
1739
1775
|
if (left.type === 'Identifier') {
|
|
@@ -1747,8 +1783,10 @@
|
|
|
1747
1783
|
variable = yield* MemberExpression$1(left, scope, { getVar: true });
|
|
1748
1784
|
}
|
|
1749
1785
|
else {
|
|
1786
|
+
const value = yield* evaluate$1(node.right, scope);
|
|
1750
1787
|
return yield* pattern$2(left, scope, { feed: value });
|
|
1751
1788
|
}
|
|
1789
|
+
const value = yield* evaluate$1(node.right, scope);
|
|
1752
1790
|
switch (node.operator) {
|
|
1753
1791
|
case '=':
|
|
1754
1792
|
variable.set(value);
|
|
@@ -1789,15 +1827,27 @@
|
|
|
1789
1827
|
case '&=':
|
|
1790
1828
|
variable.set(variable.get() & value);
|
|
1791
1829
|
return variable.get();
|
|
1830
|
+
case '??=':
|
|
1831
|
+
variable.set((_a = variable.get()) !== null && _a !== void 0 ? _a : value);
|
|
1832
|
+
return variable.get();
|
|
1833
|
+
case '&&=':
|
|
1834
|
+
variable.set(variable.get() && value);
|
|
1835
|
+
return variable.get();
|
|
1836
|
+
case '||=':
|
|
1837
|
+
variable.set(variable.get() || value);
|
|
1838
|
+
return variable.get();
|
|
1792
1839
|
default: throw new SyntaxError(`Unexpected token ${node.operator}`);
|
|
1793
1840
|
}
|
|
1794
1841
|
}
|
|
1795
1842
|
function* LogicalExpression$1(node, scope) {
|
|
1843
|
+
var _a;
|
|
1796
1844
|
switch (node.operator) {
|
|
1797
1845
|
case '||':
|
|
1798
1846
|
return (yield* evaluate$1(node.left, scope)) || (yield* evaluate$1(node.right, scope));
|
|
1799
1847
|
case '&&':
|
|
1800
1848
|
return (yield* evaluate$1(node.left, scope)) && (yield* evaluate$1(node.right, scope));
|
|
1849
|
+
case '??':
|
|
1850
|
+
return (_a = (yield* evaluate$1(node.left, scope))) !== null && _a !== void 0 ? _a : (yield* evaluate$1(node.right, scope));
|
|
1801
1851
|
default:
|
|
1802
1852
|
throw new SyntaxError(`Unexpected token ${node.operator}`);
|
|
1803
1853
|
}
|
|
@@ -1836,9 +1886,15 @@
|
|
|
1836
1886
|
const getter = getGetter(object, key);
|
|
1837
1887
|
if (node.object.type === 'Super' && getter) {
|
|
1838
1888
|
const thisObject = scope.find('this').get();
|
|
1889
|
+
if (node.optional && thisObject == null) {
|
|
1890
|
+
return undefined;
|
|
1891
|
+
}
|
|
1839
1892
|
return getter.call(thisObject);
|
|
1840
1893
|
}
|
|
1841
1894
|
else {
|
|
1895
|
+
if (node.optional && object == null) {
|
|
1896
|
+
return undefined;
|
|
1897
|
+
}
|
|
1842
1898
|
return object[key];
|
|
1843
1899
|
}
|
|
1844
1900
|
}
|
|
@@ -1853,6 +1909,9 @@
|
|
|
1853
1909
|
let object;
|
|
1854
1910
|
if (node.callee.type === 'MemberExpression') {
|
|
1855
1911
|
object = yield* MemberExpression$1(node.callee, scope, { getObj: true });
|
|
1912
|
+
if (node.callee.optional && object == null) {
|
|
1913
|
+
return undefined;
|
|
1914
|
+
}
|
|
1856
1915
|
let key;
|
|
1857
1916
|
if (node.callee.computed) {
|
|
1858
1917
|
key = yield* evaluate$1(node.callee.property, scope);
|
|
@@ -1867,6 +1926,9 @@
|
|
|
1867
1926
|
else {
|
|
1868
1927
|
func = object[key];
|
|
1869
1928
|
}
|
|
1929
|
+
if (node.optional && func == null) {
|
|
1930
|
+
return undefined;
|
|
1931
|
+
}
|
|
1870
1932
|
if (typeof func !== 'function') {
|
|
1871
1933
|
throw new TypeError(`${key} is not a function`);
|
|
1872
1934
|
}
|
|
@@ -1877,6 +1939,9 @@
|
|
|
1877
1939
|
else {
|
|
1878
1940
|
object = scope.find('this').get();
|
|
1879
1941
|
func = yield* evaluate$1(node.callee, scope);
|
|
1942
|
+
if (node.optional && func == null) {
|
|
1943
|
+
return undefined;
|
|
1944
|
+
}
|
|
1880
1945
|
if (typeof func !== 'function' || node.callee.type !== 'Super' && func[CLSCTOR]) {
|
|
1881
1946
|
let name;
|
|
1882
1947
|
if (node.callee.type === 'Identifier') {
|
|
@@ -2021,6 +2086,9 @@
|
|
|
2021
2086
|
function* SpreadElement$1(node, scope) {
|
|
2022
2087
|
return yield* evaluate$1(node.argument, scope);
|
|
2023
2088
|
}
|
|
2089
|
+
function* ChainExpression$1(node, scope) {
|
|
2090
|
+
return yield* evaluate$1(node.expression, scope);
|
|
2091
|
+
}
|
|
2024
2092
|
function* YieldExpression(node, scope) {
|
|
2025
2093
|
const res = yield* evaluate$1(node.argument, scope);
|
|
2026
2094
|
return node.delegate ? yield* res : yield res;
|
|
@@ -2054,6 +2122,7 @@
|
|
|
2054
2122
|
ClassExpression: ClassExpression$1,
|
|
2055
2123
|
Super: Super$1,
|
|
2056
2124
|
SpreadElement: SpreadElement$1,
|
|
2125
|
+
ChainExpression: ChainExpression$1,
|
|
2057
2126
|
YieldExpression: YieldExpression,
|
|
2058
2127
|
AwaitExpression: AwaitExpression
|
|
2059
2128
|
});
|
|
@@ -2491,7 +2560,10 @@
|
|
|
2491
2560
|
function* ClassBody$1(node, scope, options = {}) {
|
|
2492
2561
|
const { klass, superClass } = options;
|
|
2493
2562
|
for (let i = 0; i < node.body.length; i++) {
|
|
2494
|
-
|
|
2563
|
+
const def = node.body[i];
|
|
2564
|
+
if (def.type === 'MethodDefinition') {
|
|
2565
|
+
yield* MethodDefinition$1(def, scope, { klass, superClass });
|
|
2566
|
+
}
|
|
2495
2567
|
}
|
|
2496
2568
|
}
|
|
2497
2569
|
function* MethodDefinition$1(node, scope, options = {}) {
|
|
@@ -2710,7 +2782,7 @@
|
|
|
2710
2782
|
yield* RestElement$1(param, subScope, { kind: 'var', feed: args.slice(i) });
|
|
2711
2783
|
}
|
|
2712
2784
|
else {
|
|
2713
|
-
yield* pattern$2(param, subScope, { feed: args[i] });
|
|
2785
|
+
yield* pattern$2(param, subScope, { kind: 'var', feed: args[i] });
|
|
2714
2786
|
}
|
|
2715
2787
|
}
|
|
2716
2788
|
let result;
|
|
@@ -2786,7 +2858,7 @@
|
|
|
2786
2858
|
const methodBody = node.body.body;
|
|
2787
2859
|
for (let i = 0; i < methodBody.length; i++) {
|
|
2788
2860
|
const method = methodBody[i];
|
|
2789
|
-
if (method.kind === 'constructor') {
|
|
2861
|
+
if (method.type === 'MethodDefinition' && method.kind === 'constructor') {
|
|
2790
2862
|
klass = createFunc(method.value, scope, { superClass, isCtor: true });
|
|
2791
2863
|
break;
|
|
2792
2864
|
}
|
|
@@ -2949,7 +3021,7 @@
|
|
|
2949
3021
|
RestElement(param, subScope, { kind: 'var', feed: args.slice(i) });
|
|
2950
3022
|
}
|
|
2951
3023
|
else {
|
|
2952
|
-
pattern$3(param, subScope, { feed: args[i] });
|
|
3024
|
+
pattern$3(param, subScope, { kind: 'var', feed: args[i] });
|
|
2953
3025
|
}
|
|
2954
3026
|
}
|
|
2955
3027
|
let result;
|
|
@@ -2997,7 +3069,7 @@
|
|
|
2997
3069
|
const methodBody = node.body.body;
|
|
2998
3070
|
for (let i = 0; i < methodBody.length; i++) {
|
|
2999
3071
|
const method = methodBody[i];
|
|
3000
|
-
if (method.kind === 'constructor') {
|
|
3072
|
+
if (method.type === 'MethodDefinition' && method.kind === 'constructor') {
|
|
3001
3073
|
klass = createFunc$1(method.value, scope, { superClass, isCtor: true });
|
|
3002
3074
|
break;
|
|
3003
3075
|
}
|
|
@@ -3037,14 +3109,17 @@
|
|
|
3037
3109
|
return result;
|
|
3038
3110
|
}
|
|
3039
3111
|
|
|
3112
|
+
const latestVer = 15;
|
|
3040
3113
|
class Sval {
|
|
3041
3114
|
constructor(options = {}) {
|
|
3042
|
-
this.options = {};
|
|
3115
|
+
this.options = { ecmaVersion: 'latest' };
|
|
3043
3116
|
this.scope = new Scope(null, true);
|
|
3044
3117
|
this.exports = {};
|
|
3045
|
-
let { ecmaVer =
|
|
3046
|
-
|
|
3047
|
-
|
|
3118
|
+
let { ecmaVer = 'latest', sandBox = true } = options;
|
|
3119
|
+
if (typeof ecmaVer === 'number') {
|
|
3120
|
+
ecmaVer -= ecmaVer < 2015 ? 0 : 2009;
|
|
3121
|
+
}
|
|
3122
|
+
if (ecmaVer !== 'latest' && ecmaVer !== 3 && (ecmaVer < 5 || ecmaVer > latestVer)) {
|
|
3048
3123
|
throw new Error(`unsupported ecmaVer`);
|
|
3049
3124
|
}
|
|
3050
3125
|
this.options.ecmaVersion = ecmaVer;
|