babel-plugin-vasille 0.99.5 → 3.1.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/README.md +3 -4
- package/lib/call.js +19 -17
- package/lib/css-transformer.js +18 -21
- package/lib/expression.js +107 -100
- package/lib/index.js +1 -1
- package/lib/internal.js +17 -2
- package/lib/jsx-detect.js +11 -9
- package/lib/jsx.js +63 -64
- package/lib/lib.js +67 -49
- package/lib/mesh.js +258 -319
- package/lib/transformer.js +16 -40
- package/lib-node/call.js +38 -26
- package/lib-node/css-transformer.js +38 -31
- package/lib-node/expression.js +129 -108
- package/lib-node/index.js +2 -2
- package/lib-node/internal.js +35 -10
- package/lib-node/jsx-detect.js +28 -16
- package/lib-node/jsx.js +90 -80
- package/lib-node/lib.js +90 -61
- package/lib-node/mesh.js +291 -343
- package/lib-node/transformer.js +36 -50
- package/package.json +18 -14
package/README.md
CHANGED
|
@@ -103,12 +103,11 @@ All of these are supported:
|
|
|
103
103
|
* [x] Develop the `Vasille JSX` library.
|
|
104
104
|
* [x] `100%` Test Coverage for the JSX library.
|
|
105
105
|
* [x] Develop the `Vasille Babel Plugin`.
|
|
106
|
-
* [
|
|
106
|
+
* [x] `100%` Test Coverage fot babel plugin.
|
|
107
107
|
* [x] Add CSS support (define styles in components).
|
|
108
|
-
* [ ] Add custom `input` components with 2-way value binding.
|
|
109
108
|
* [ ] Add router.
|
|
110
|
-
* [ ]
|
|
111
|
-
* [ ] Develop
|
|
109
|
+
* [ ] Add SSR (server side rendering).
|
|
110
|
+
* [ ] Develop tools extension for debugging.
|
|
112
111
|
|
|
113
112
|
## Questions
|
|
114
113
|
|
package/lib/call.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import * as t from "@babel/types";
|
|
2
|
-
import { ctx } from "./internal";
|
|
2
|
+
import { ctx } from "./internal.js";
|
|
3
3
|
export const composeOnly = [
|
|
4
4
|
"forward",
|
|
5
5
|
"watch",
|
|
6
6
|
"ref",
|
|
7
7
|
"bind",
|
|
8
8
|
"value",
|
|
9
|
+
"awaited",
|
|
9
10
|
"arrayModel",
|
|
10
11
|
"mapModel",
|
|
11
12
|
"setModel",
|
|
@@ -19,9 +20,9 @@ export const styleOnly = [
|
|
|
19
20
|
"laptop",
|
|
20
21
|
"prefersDark",
|
|
21
22
|
"prefersLight",
|
|
22
|
-
"
|
|
23
|
+
"styleSheet",
|
|
23
24
|
];
|
|
24
|
-
export const requiresContext = ["awaited"
|
|
25
|
+
export const requiresContext = ["awaited"];
|
|
25
26
|
const requiresContextSet = new Set(requiresContext);
|
|
26
27
|
export function calls(node, names, internal) {
|
|
27
28
|
const set = new Set(names);
|
|
@@ -33,32 +34,33 @@ export function calls(node, names, internal) {
|
|
|
33
34
|
if (requiresContextSet.has(callee.name) && t.isCallExpression(node)) {
|
|
34
35
|
node.arguments.unshift(ctx);
|
|
35
36
|
}
|
|
37
|
+
if (mapped === "state") {
|
|
38
|
+
internal.stateOnly = true;
|
|
39
|
+
}
|
|
40
|
+
if (mapped === "compose" || mapped === "extend") {
|
|
41
|
+
internal.stateOnly = false;
|
|
42
|
+
}
|
|
36
43
|
return mapped;
|
|
37
44
|
}
|
|
38
45
|
return false;
|
|
39
46
|
}
|
|
40
47
|
const global = internal.stack.get(internal.global) === undefined;
|
|
41
|
-
|
|
42
|
-
if (
|
|
43
|
-
|
|
48
|
+
let propName = null;
|
|
49
|
+
if (t.isMemberExpression(callee)) {
|
|
50
|
+
if (t.isIdentifier(callee.property)) {
|
|
51
|
+
propName = callee.property.name;
|
|
52
|
+
}
|
|
53
|
+
else if (t.isStringLiteral(callee.property)) {
|
|
54
|
+
propName = callee.property.value;
|
|
55
|
+
}
|
|
44
56
|
}
|
|
45
|
-
const propName = t.isMemberExpression(callee)
|
|
46
|
-
? t.isIdentifier(callee.property)
|
|
47
|
-
? callee.property.name
|
|
48
|
-
: t.isStringLiteral(callee.property)
|
|
49
|
-
? callee.property.value
|
|
50
|
-
: null
|
|
51
|
-
: null;
|
|
52
57
|
if (t.isMemberExpression(callee) && t.isIdentifier(callee.object) && propName) {
|
|
53
58
|
if (global && callee.object.name === internal.global && set.has(propName)) {
|
|
54
|
-
if (requiresContextSet.has(
|
|
59
|
+
if (requiresContextSet.has(propName) && t.isCallExpression(node)) {
|
|
55
60
|
node.arguments.unshift(ctx);
|
|
56
61
|
}
|
|
57
62
|
return callee.object.name;
|
|
58
63
|
}
|
|
59
|
-
if (cssGlobal && callee.object.name === internal.cssGlobal && set.has(propName)) {
|
|
60
|
-
return callee.object.name;
|
|
61
|
-
}
|
|
62
64
|
}
|
|
63
65
|
}
|
|
64
66
|
return false;
|
package/lib/css-transformer.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as t from "@babel/types";
|
|
2
|
-
import { calls } from "./call";
|
|
2
|
+
import { calls } from "./call.js";
|
|
3
3
|
function tryProcessProp(path, pseudo, media, internal) {
|
|
4
4
|
if (t.isObjectMethod(path.node)) {
|
|
5
|
-
throw path.buildCodeFrameError("Object methods not supported here");
|
|
5
|
+
throw path.buildCodeFrameError("Vasille: Object methods not supported here");
|
|
6
6
|
}
|
|
7
7
|
if (t.isSpreadElement(path.node)) {
|
|
8
|
-
throw path.buildCodeFrameError("Spread element not
|
|
8
|
+
throw path.buildCodeFrameError("Vasille: Spread element not supported here");
|
|
9
9
|
}
|
|
10
10
|
return processProp(path, pseudo, media, internal);
|
|
11
11
|
}
|
|
@@ -14,7 +14,7 @@ function processValue(name, path, pseudo, theme, media, mediaDefault, allowFallb
|
|
|
14
14
|
if (calls(path.node, ["theme"], internal)) {
|
|
15
15
|
const call = path.node;
|
|
16
16
|
if (theme) {
|
|
17
|
-
throw path.buildCodeFrameError("Vasille:
|
|
17
|
+
throw path.buildCodeFrameError("Vasille: The theme seems the be defined twice");
|
|
18
18
|
}
|
|
19
19
|
if (t.isStringLiteral(call.arguments[0])) {
|
|
20
20
|
return processValue(name, path.get("arguments")[1], pseudo, `body.${call.arguments[0].value}`, media, mediaDefault, false, internal);
|
|
@@ -27,7 +27,7 @@ function processValue(name, path, pseudo, theme, media, mediaDefault, allowFallb
|
|
|
27
27
|
}
|
|
28
28
|
if (calls(path.node, ["dark"], internal)) {
|
|
29
29
|
if (theme) {
|
|
30
|
-
throw path.buildCodeFrameError("Vasille:
|
|
30
|
+
throw path.buildCodeFrameError("Vasille: The theme seem the be defined twice");
|
|
31
31
|
}
|
|
32
32
|
return processValue(name, path.get("arguments")[0], pseudo, `.dark`, media, mediaDefault, false, internal);
|
|
33
33
|
}
|
|
@@ -79,32 +79,32 @@ function processValue(name, path, pseudo, theme, media, mediaDefault, allowFallb
|
|
|
79
79
|
return processValue(name, path, pseudo, theme, media, mediaDefault, false, internal);
|
|
80
80
|
}
|
|
81
81
|
else {
|
|
82
|
-
throw path.buildCodeFrameError("Vasille:
|
|
82
|
+
throw path.buildCodeFrameError("Vasille: Expected expression");
|
|
83
83
|
}
|
|
84
84
|
})
|
|
85
85
|
.flat(1),
|
|
86
86
|
];
|
|
87
87
|
}
|
|
88
88
|
else {
|
|
89
|
-
throw path.buildCodeFrameError("Vasille: Only numbers arrays are
|
|
89
|
+
throw path.buildCodeFrameError("Vasille: Only numbers arrays are supported here");
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
throw path.buildCodeFrameError("Vasille: Failed o parse value, it is not a string, number or array");
|
|
93
93
|
}
|
|
94
94
|
function processProp(path, pseudo, media, internal) {
|
|
95
95
|
let name;
|
|
96
|
-
if (t.isIdentifier(path.node.key)) {
|
|
96
|
+
if (t.isIdentifier(path.node.key) && !path.node.computed) {
|
|
97
97
|
name = path.node.key.name;
|
|
98
98
|
}
|
|
99
99
|
else if (t.isStringLiteral(path.node.key)) {
|
|
100
100
|
name = path.node.key.value;
|
|
101
101
|
}
|
|
102
102
|
else {
|
|
103
|
-
throw path.get("key").buildCodeFrameError("Vasille:
|
|
103
|
+
throw path.get("key").buildCodeFrameError("Vasille: Incompatible key, expect identifier or string literal");
|
|
104
104
|
}
|
|
105
105
|
if (name.startsWith("@")) {
|
|
106
106
|
if (media || pseudo) {
|
|
107
|
-
throw path.get("key").buildCodeFrameError("Vasille: Media queries allowed
|
|
107
|
+
throw path.get("key").buildCodeFrameError("Vasille: Media queries allowed only in the root of style");
|
|
108
108
|
}
|
|
109
109
|
if (t.isObjectExpression(path.node.value)) {
|
|
110
110
|
return path.get("value")
|
|
@@ -115,12 +115,12 @@ function processProp(path, pseudo, media, internal) {
|
|
|
115
115
|
.flat(1);
|
|
116
116
|
}
|
|
117
117
|
else {
|
|
118
|
-
throw path.get("value").buildCodeFrameError("Vasille:
|
|
118
|
+
throw path.get("value").buildCodeFrameError("Vasille: Expected object expression");
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
if (name.startsWith(":")) {
|
|
122
122
|
if (pseudo) {
|
|
123
|
-
throw path.get("key").buildCodeFrameError("Recursive pseudo classes are
|
|
123
|
+
throw path.get("key").buildCodeFrameError("Vasille: Recursive pseudo classes are restricted");
|
|
124
124
|
}
|
|
125
125
|
if (t.isObjectExpression(path.node.value)) {
|
|
126
126
|
return path.get("value")
|
|
@@ -131,31 +131,28 @@ function processProp(path, pseudo, media, internal) {
|
|
|
131
131
|
.flat(1);
|
|
132
132
|
}
|
|
133
133
|
else {
|
|
134
|
-
throw path.get("value").buildCodeFrameError("Vasille:
|
|
134
|
+
throw path.get("value").buildCodeFrameError("Vasille: Expected object expression");
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
return processValue(name, path.get("value"), pseudo, "", media, [], true, internal);
|
|
138
138
|
}
|
|
139
139
|
export function findStyleInNode(path, internal) {
|
|
140
|
-
if (t.isExpressionStatement(path.node)) {
|
|
141
|
-
return findStyleInNode(path.get("expression"), internal);
|
|
142
|
-
}
|
|
143
140
|
if (t.isExportNamedDeclaration(path.node)) {
|
|
144
141
|
return findStyleInNode(path.get("declaration"), internal);
|
|
145
142
|
}
|
|
146
143
|
if (t.isVariableDeclaration(path.node) &&
|
|
147
144
|
path.node.declarations.length === 1 &&
|
|
148
|
-
calls(path.node.declarations[0].init, ["
|
|
145
|
+
calls(path.node.declarations[0].init, ["styleSheet"], internal)) {
|
|
149
146
|
const call = path.node.declarations[0].init;
|
|
150
147
|
const callPath = path
|
|
151
148
|
.get("declarations")[0]
|
|
152
149
|
.get("init");
|
|
153
150
|
const objPath = callPath.get("arguments")[0];
|
|
154
151
|
if (call.arguments.length !== 1) {
|
|
155
|
-
throw callPath.buildCodeFrameError("Vasille:
|
|
152
|
+
throw callPath.buildCodeFrameError("Vasille: styleSheet function has 1 parameter");
|
|
156
153
|
}
|
|
157
154
|
if (!t.isObjectExpression(call.arguments[0])) {
|
|
158
|
-
throw objPath.buildCodeFrameError("Vasille:
|
|
155
|
+
throw objPath.buildCodeFrameError("Vasille: Expected object expression");
|
|
159
156
|
}
|
|
160
157
|
for (const path of objPath.get("properties")) {
|
|
161
158
|
if (!t.isObjectProperty(path.node)) {
|
|
@@ -163,9 +160,9 @@ export function findStyleInNode(path, internal) {
|
|
|
163
160
|
}
|
|
164
161
|
const prop = path;
|
|
165
162
|
if (!t.isObjectExpression(prop.node.value)) {
|
|
166
|
-
throw prop.get("value").buildCodeFrameError("Vasille:
|
|
163
|
+
throw prop.get("value").buildCodeFrameError("Vasille: Expected object expression");
|
|
167
164
|
}
|
|
168
|
-
if (!(t.isIdentifier(prop.node.key) || t.isStringLiteral(prop.node.key))) {
|
|
165
|
+
if (!((t.isIdentifier(prop.node.key) && !prop.node.computed) || t.isStringLiteral(prop.node.key))) {
|
|
169
166
|
throw prop.get("key").buildCodeFrameError("Vasille: Expected identifier of string literal");
|
|
170
167
|
}
|
|
171
168
|
const unsorted = [];
|
package/lib/expression.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as t from "@babel/types";
|
|
2
|
-
import {
|
|
2
|
+
import { calls, composeOnly } from "./call.js";
|
|
3
|
+
import { VariableScope } from "./internal.js";
|
|
3
4
|
export function encodeName(name) {
|
|
4
5
|
return t.identifier(`Vasille_${name}`);
|
|
5
6
|
}
|
|
@@ -10,16 +11,17 @@ function addIdentifier(path, search) {
|
|
|
10
11
|
path.replaceWith(encodeName(path.node.name));
|
|
11
12
|
}
|
|
12
13
|
function stringify(node) {
|
|
13
|
-
|
|
14
|
-
return node.name;
|
|
15
|
-
}
|
|
14
|
+
let name = "";
|
|
16
15
|
if (t.isStringLiteral(node)) {
|
|
17
|
-
|
|
16
|
+
name = node.value;
|
|
18
17
|
}
|
|
19
18
|
if (t.isPrivateName(node)) {
|
|
20
|
-
|
|
19
|
+
name = node.id.name;
|
|
20
|
+
}
|
|
21
|
+
if (t.isIdentifier(node)) {
|
|
22
|
+
name = node.name;
|
|
21
23
|
}
|
|
22
|
-
return
|
|
24
|
+
return name;
|
|
23
25
|
}
|
|
24
26
|
function extractMemberName(path, search) {
|
|
25
27
|
const names = [];
|
|
@@ -30,10 +32,11 @@ function extractMemberName(path, search) {
|
|
|
30
32
|
throw path.buildCodeFrameError("Vasille: The reactive/observable value is nested");
|
|
31
33
|
}
|
|
32
34
|
it = it.object;
|
|
33
|
-
names.push();
|
|
35
|
+
names.push(name);
|
|
34
36
|
}
|
|
35
37
|
names.push(stringify(it));
|
|
36
|
-
if (t.isIdentifier(it) &&
|
|
38
|
+
if (t.isIdentifier(it) &&
|
|
39
|
+
search.stack.get(it.name, VariableScope.Local) === 1 /* VariableState.Ignored */) {
|
|
37
40
|
throw path.buildCodeFrameError("Vasille: This node cannot be processed, the root of expression is a local variable");
|
|
38
41
|
}
|
|
39
42
|
return names.reverse().join("_");
|
|
@@ -53,35 +56,65 @@ function addExternalIValue(path, search) {
|
|
|
53
56
|
path.replaceWith(encodeName(name));
|
|
54
57
|
}
|
|
55
58
|
function meshIdentifier(path, internal) {
|
|
56
|
-
|
|
57
|
-
if (state === 2 /* VariableState.Reactive */ || state === 4 /* VariableState.ReactivePointer */) {
|
|
59
|
+
if (idIsIValue(path, internal)) {
|
|
58
60
|
path.replaceWith(t.memberExpression(path.node, t.identifier("$")));
|
|
59
61
|
}
|
|
60
62
|
}
|
|
63
|
+
export function idIsIValue(path, internal, scope) {
|
|
64
|
+
const node = path.node;
|
|
65
|
+
return (REACTIVE_STATES.includes(internal.stack.get(node.name, scope)) &&
|
|
66
|
+
(!t.isMemberExpression(path.parent) || path.parent.object === node));
|
|
67
|
+
}
|
|
68
|
+
export function idIsLocal(path, internal) {
|
|
69
|
+
return internal.stack.get(path.node.name, VariableScope.Local) !== undefined;
|
|
70
|
+
}
|
|
71
|
+
export function memberIsIValue(node, internal, scope) {
|
|
72
|
+
return ((t.isIdentifier(node.object) &&
|
|
73
|
+
(internal.stack.get(node.object.name, scope) === 3 /* VariableState.ReactiveObject */ ||
|
|
74
|
+
(t.isIdentifier(node.property) &&
|
|
75
|
+
node.property.name.startsWith("$") &&
|
|
76
|
+
!node.property.name.startsWith("$$") &&
|
|
77
|
+
node.property.name !== "$") ||
|
|
78
|
+
(t.isStringLiteral(node.property) &&
|
|
79
|
+
node.property.value.startsWith("$") &&
|
|
80
|
+
!node.property.value.startsWith("$$") &&
|
|
81
|
+
node.property.value !== "$"))) ||
|
|
82
|
+
(t.isMemberExpression(node.object) &&
|
|
83
|
+
((t.isIdentifier(node.object.property) && node.object.property.name.startsWith("$$")) ||
|
|
84
|
+
(t.isStringLiteral(node.object.property) && node.object.property.value.startsWith("$$")))));
|
|
85
|
+
}
|
|
86
|
+
export function nodeIsReactiveObject(path, internal) {
|
|
87
|
+
const node = path.node;
|
|
88
|
+
if (t.isIdentifier(node)) {
|
|
89
|
+
return internal.stack.get(node.name) === 3 /* VariableState.ReactiveObject */;
|
|
90
|
+
}
|
|
91
|
+
if (t.isOptionalMemberExpression(node) || t.isMemberExpression(node)) {
|
|
92
|
+
return ((t.isIdentifier(node.property) && node.property.name.startsWith("$$")) ||
|
|
93
|
+
(t.isStringLiteral(node.property) && node.property.value.startsWith("$$")));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
61
96
|
function meshMember(path, internal) {
|
|
62
|
-
if (
|
|
97
|
+
if (memberIsIValue(path.node, internal)) {
|
|
63
98
|
path.replaceWith(t.memberExpression(path.node, t.identifier("$")));
|
|
64
99
|
}
|
|
65
100
|
}
|
|
66
101
|
function meshLValue(path, internal) {
|
|
67
|
-
|
|
102
|
+
const node = path.node;
|
|
103
|
+
if (t.isIdentifier(node)) {
|
|
68
104
|
meshIdentifier(path, internal);
|
|
69
105
|
}
|
|
70
|
-
else if (t.isMemberExpression(
|
|
106
|
+
else if (t.isMemberExpression(node) || t.isOptionalMemberExpression(node)) {
|
|
71
107
|
meshMember(path, internal);
|
|
72
108
|
}
|
|
73
|
-
else {
|
|
74
|
-
path.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
meshMember(path, internal);
|
|
83
|
-
},
|
|
84
|
-
});
|
|
109
|
+
else if (t.isArrayPattern(node)) {
|
|
110
|
+
for (const item of path.get("elements")) {
|
|
111
|
+
if (t.isOptionalMemberExpression(item.node) || t.isLVal(item.node)) {
|
|
112
|
+
meshLValue(item, internal);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
else if (t.isRestElement(node)) {
|
|
117
|
+
meshLValue(path.get("argument"), internal);
|
|
85
118
|
}
|
|
86
119
|
}
|
|
87
120
|
export function checkNode(path, internal) {
|
|
@@ -89,29 +122,31 @@ export function checkNode(path, internal) {
|
|
|
89
122
|
external: internal,
|
|
90
123
|
found: new Map(),
|
|
91
124
|
self: null,
|
|
92
|
-
stack:
|
|
125
|
+
stack: internal.stack,
|
|
93
126
|
};
|
|
94
127
|
if (t.isIdentifier(path.node)) {
|
|
95
|
-
|
|
96
|
-
if (state === 2 /* VariableState.Reactive */ || state == 4 /* VariableState.ReactivePointer */) {
|
|
128
|
+
if (idIsIValue(path, internal)) {
|
|
97
129
|
search.self = path.node;
|
|
98
130
|
}
|
|
99
131
|
}
|
|
100
132
|
if (t.isMemberExpression(path.node)) {
|
|
101
|
-
if (
|
|
102
|
-
internal.stack.get(path.node.object.name) === 3 /* VariableState.ReactiveObject */) {
|
|
133
|
+
if (memberIsIValue(path.node, internal)) {
|
|
103
134
|
search.self = path.node;
|
|
104
135
|
}
|
|
105
|
-
if (t.isIdentifier(path.node.property) && path.node.property.name === "$") {
|
|
136
|
+
else if (t.isIdentifier(path.node.property) && path.node.property.name === "$") {
|
|
106
137
|
search.self = path.node.object;
|
|
107
138
|
}
|
|
108
139
|
}
|
|
109
140
|
if (search.self) {
|
|
110
141
|
return search;
|
|
111
142
|
}
|
|
143
|
+
internal.stack.fixLocalIndex();
|
|
144
|
+
internal.stack.push();
|
|
112
145
|
if (t.isExpression(path.node)) {
|
|
113
146
|
checkExpression(path, search);
|
|
114
147
|
}
|
|
148
|
+
internal.stack.pop();
|
|
149
|
+
internal.stack.resetLocalIndex();
|
|
115
150
|
return search;
|
|
116
151
|
}
|
|
117
152
|
export function checkOrIgnoreAllExpressions(nodePaths, search) {
|
|
@@ -136,17 +171,15 @@ export function checkAllUnknown(paths, internal) {
|
|
|
136
171
|
}
|
|
137
172
|
}
|
|
138
173
|
}
|
|
139
|
-
export function
|
|
174
|
+
export function checkOrIgnoreExpression(path, search) {
|
|
140
175
|
if (t.isExpression(path.node)) {
|
|
141
176
|
checkExpression(path, search);
|
|
142
177
|
}
|
|
143
178
|
}
|
|
179
|
+
const REACTIVE_STATES = [2 /* VariableState.Reactive */, 4 /* VariableState.ReactivePointer */];
|
|
144
180
|
export function checkExpression(nodePath, search) {
|
|
145
181
|
const expr = nodePath.node;
|
|
146
|
-
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
switch (expr.type) {
|
|
182
|
+
switch (expr && expr.type) {
|
|
150
183
|
case "TemplateLiteral": {
|
|
151
184
|
const path = nodePath;
|
|
152
185
|
checkOrIgnoreAllExpressions(path.get("expressions"), search);
|
|
@@ -155,11 +188,13 @@ export function checkExpression(nodePath, search) {
|
|
|
155
188
|
case "TaggedTemplateExpression": {
|
|
156
189
|
const path = nodePath;
|
|
157
190
|
checkExpression(path.get("quasi"), search);
|
|
191
|
+
path.get("");
|
|
158
192
|
break;
|
|
159
193
|
}
|
|
160
194
|
case "Identifier": {
|
|
161
|
-
if (
|
|
162
|
-
if (search.external
|
|
195
|
+
if (expr && t.isIdentifier(expr)) {
|
|
196
|
+
if (idIsIValue(nodePath, search.external, VariableScope.Global) &&
|
|
197
|
+
!idIsLocal(nodePath, search.external)) {
|
|
163
198
|
addIdentifier(nodePath, search);
|
|
164
199
|
}
|
|
165
200
|
}
|
|
@@ -170,14 +205,12 @@ export function checkExpression(nodePath, search) {
|
|
|
170
205
|
checkAllUnknown(path.get("elements"), search);
|
|
171
206
|
break;
|
|
172
207
|
}
|
|
173
|
-
case "TupleExpression": {
|
|
174
|
-
const path = nodePath;
|
|
175
|
-
checkAllUnknown(path.get("elements"), search);
|
|
176
|
-
break;
|
|
177
|
-
}
|
|
178
208
|
case "CallExpression": {
|
|
179
209
|
const path = nodePath;
|
|
180
|
-
|
|
210
|
+
if (calls(path.node, composeOnly, search.external)) {
|
|
211
|
+
throw path.buildCodeFrameError("Vasille: Usage of hints is restricted here");
|
|
212
|
+
}
|
|
213
|
+
checkOrIgnoreExpression(path.get("callee"), search);
|
|
181
214
|
checkAllUnknown(path.get("arguments"), search);
|
|
182
215
|
break;
|
|
183
216
|
}
|
|
@@ -197,19 +230,21 @@ export function checkExpression(nodePath, search) {
|
|
|
197
230
|
case "OptionalMemberExpression": {
|
|
198
231
|
const path = nodePath;
|
|
199
232
|
const node = path.node;
|
|
200
|
-
|
|
201
|
-
chekOrIgnoreExpression(path.get("property"), search);
|
|
202
|
-
if (t.isIdentifier(node.object) && search.external.stack.get(node.object.name) === 3 /* VariableState.ReactiveObject */) {
|
|
233
|
+
if (memberIsIValue(node, search.external, VariableScope.Global)) {
|
|
203
234
|
addMemberExpr(path, search);
|
|
204
235
|
}
|
|
205
236
|
else if (t.isIdentifier(node.property) && node.property.name === "$") {
|
|
206
237
|
addExternalIValue(path, search);
|
|
207
238
|
}
|
|
239
|
+
else {
|
|
240
|
+
checkExpression(path.get("object"), search);
|
|
241
|
+
checkOrIgnoreExpression(path.get("property"), search);
|
|
242
|
+
}
|
|
208
243
|
break;
|
|
209
244
|
}
|
|
210
245
|
case "BinaryExpression": {
|
|
211
246
|
const path = nodePath;
|
|
212
|
-
|
|
247
|
+
checkOrIgnoreExpression(path.get("left"), search);
|
|
213
248
|
checkExpression(path.get("right"), search);
|
|
214
249
|
break;
|
|
215
250
|
}
|
|
@@ -228,7 +263,7 @@ export function checkExpression(nodePath, search) {
|
|
|
228
263
|
}
|
|
229
264
|
case "NewExpression": {
|
|
230
265
|
const path = nodePath;
|
|
231
|
-
|
|
266
|
+
checkOrIgnoreExpression(path.get("callee"), search);
|
|
232
267
|
checkAllUnknown(path.get("arguments"), search);
|
|
233
268
|
break;
|
|
234
269
|
}
|
|
@@ -237,11 +272,6 @@ export function checkExpression(nodePath, search) {
|
|
|
237
272
|
checkAllExpressions(path.get("expressions"), search);
|
|
238
273
|
break;
|
|
239
274
|
}
|
|
240
|
-
case "ParenthesizedExpression": {
|
|
241
|
-
const path = nodePath;
|
|
242
|
-
checkExpression(path.get("expression"), search);
|
|
243
|
-
break;
|
|
244
|
-
}
|
|
245
275
|
case "UnaryExpression": {
|
|
246
276
|
const path = nodePath;
|
|
247
277
|
checkExpression(path.get("argument"), search);
|
|
@@ -249,7 +279,10 @@ export function checkExpression(nodePath, search) {
|
|
|
249
279
|
}
|
|
250
280
|
case "UpdateExpression": {
|
|
251
281
|
const path = nodePath;
|
|
252
|
-
|
|
282
|
+
const arg = path.node.argument;
|
|
283
|
+
if (t.isLVal(arg)) {
|
|
284
|
+
meshLValue(path.get("argument"), search.external);
|
|
285
|
+
}
|
|
253
286
|
break;
|
|
254
287
|
}
|
|
255
288
|
case "YieldExpression": {
|
|
@@ -262,27 +295,6 @@ export function checkExpression(nodePath, search) {
|
|
|
262
295
|
checkExpression(path.get("argument"), search);
|
|
263
296
|
break;
|
|
264
297
|
}
|
|
265
|
-
case "TypeCastExpression": {
|
|
266
|
-
const path = nodePath;
|
|
267
|
-
checkExpression(path.get("expression"), search);
|
|
268
|
-
break;
|
|
269
|
-
}
|
|
270
|
-
case "BindExpression": {
|
|
271
|
-
const path = nodePath;
|
|
272
|
-
checkExpression(path.get("callee"), search);
|
|
273
|
-
checkExpression(path.get("object"), search);
|
|
274
|
-
break;
|
|
275
|
-
}
|
|
276
|
-
case "PipelineTopicExpression": {
|
|
277
|
-
const path = nodePath;
|
|
278
|
-
checkExpression(path.get("expression"), search);
|
|
279
|
-
break;
|
|
280
|
-
}
|
|
281
|
-
case "PipelineBareFunction": {
|
|
282
|
-
const path = nodePath;
|
|
283
|
-
checkExpression(path.get("callee"), search);
|
|
284
|
-
break;
|
|
285
|
-
}
|
|
286
298
|
case "TSInstantiationExpression": {
|
|
287
299
|
const path = nodePath;
|
|
288
300
|
checkExpression(path.get("expression"), search);
|
|
@@ -310,12 +322,10 @@ export function checkExpression(nodePath, search) {
|
|
|
310
322
|
if (t.isObjectProperty(prop)) {
|
|
311
323
|
const path = propPath;
|
|
312
324
|
const valuePath = path.get("value");
|
|
313
|
-
if (
|
|
314
|
-
|
|
315
|
-
}
|
|
316
|
-
else {
|
|
317
|
-
chekOrIgnoreExpression(valuePath, search);
|
|
325
|
+
if (path.node.computed) {
|
|
326
|
+
checkOrIgnoreExpression(path.get("key"), search);
|
|
318
327
|
}
|
|
328
|
+
checkOrIgnoreExpression(valuePath, search);
|
|
319
329
|
}
|
|
320
330
|
else if (t.isObjectMethod(prop)) {
|
|
321
331
|
checkFunction(propPath, search);
|
|
@@ -348,9 +358,6 @@ export function checkStatements(paths, search) {
|
|
|
348
358
|
}
|
|
349
359
|
}
|
|
350
360
|
function ignoreLocals(val, search) {
|
|
351
|
-
if (t.isAssignmentPattern(val)) {
|
|
352
|
-
val = val.left;
|
|
353
|
-
}
|
|
354
361
|
if (t.isIdentifier(val)) {
|
|
355
362
|
search.stack.set(val.name, 1 /* VariableState.Ignored */);
|
|
356
363
|
}
|
|
@@ -362,18 +369,23 @@ function ignoreLocals(val, search) {
|
|
|
362
369
|
else if (t.isRestElement(prop) && t.isIdentifier(prop.argument)) {
|
|
363
370
|
search.stack.set(prop.argument.name, 1 /* VariableState.Ignored */);
|
|
364
371
|
}
|
|
372
|
+
else if (t.isObjectProperty(prop) && t.isAssignmentPattern(prop.value)) {
|
|
373
|
+
ignoreLocals(prop.value.left, search);
|
|
374
|
+
}
|
|
365
375
|
}
|
|
366
376
|
}
|
|
367
377
|
else if (t.isArrayPattern(val)) {
|
|
368
378
|
for (const element of val.elements) {
|
|
369
|
-
if (element) {
|
|
379
|
+
if (element && !t.isVoidPattern(element)) {
|
|
370
380
|
ignoreLocals(element, search);
|
|
371
381
|
}
|
|
372
382
|
}
|
|
373
383
|
}
|
|
374
384
|
else if (t.isVariableDeclaration(val)) {
|
|
375
385
|
for (const declarator of val.declarations) {
|
|
376
|
-
|
|
386
|
+
if (!t.isVoidPattern(declarator.id)) {
|
|
387
|
+
ignoreLocals(declarator.id, search);
|
|
388
|
+
}
|
|
377
389
|
}
|
|
378
390
|
}
|
|
379
391
|
}
|
|
@@ -472,12 +484,16 @@ export function checkStatement(path, search) {
|
|
|
472
484
|
checkExpression(path.get("argument"), search);
|
|
473
485
|
break;
|
|
474
486
|
case "TryStatement":
|
|
487
|
+
const handlerPath = path.get("handler");
|
|
475
488
|
checkStatement(path.get("block"), search);
|
|
489
|
+
if (handlerPath.node) {
|
|
490
|
+
checkStatement(handlerPath.get("body"), search);
|
|
491
|
+
}
|
|
492
|
+
checkStatement(path.get("finalizer"), search);
|
|
476
493
|
break;
|
|
477
494
|
case "VariableDeclaration": {
|
|
478
495
|
const _path = path;
|
|
479
496
|
for (const declaration of _path.get("declarations")) {
|
|
480
|
-
const expr = declaration.node.init;
|
|
481
497
|
ignoreLocals(declaration.node.id, search);
|
|
482
498
|
checkExpression(declaration.get("init"), search);
|
|
483
499
|
}
|
|
@@ -491,22 +507,13 @@ export function checkStatement(path, search) {
|
|
|
491
507
|
search.stack.pop();
|
|
492
508
|
break;
|
|
493
509
|
}
|
|
494
|
-
case "WithStatement": {
|
|
495
|
-
const _path = path;
|
|
496
|
-
checkExpression(_path.get("object"), search);
|
|
497
|
-
search.stack.push();
|
|
498
|
-
checkStatement(_path.get("body"), search);
|
|
499
|
-
search.stack.pop();
|
|
500
|
-
break;
|
|
501
|
-
}
|
|
502
|
-
case "ExportNamedDeclaration": {
|
|
503
|
-
checkStatement(path.get("declaration"), search);
|
|
504
|
-
break;
|
|
505
|
-
}
|
|
506
510
|
}
|
|
507
511
|
}
|
|
508
512
|
export function checkFunction(path, search) {
|
|
509
513
|
const node = path.node;
|
|
514
|
+
for (const param of node.params) {
|
|
515
|
+
ignoreLocals(param, search);
|
|
516
|
+
}
|
|
510
517
|
if (t.isExpression(node.body)) {
|
|
511
518
|
checkExpression(path.get("body"), search);
|
|
512
519
|
}
|
package/lib/index.js
CHANGED
package/lib/internal.js
CHANGED
|
@@ -1,17 +1,32 @@
|
|
|
1
1
|
import * as t from "@babel/types";
|
|
2
|
+
export var VariableScope;
|
|
3
|
+
(function (VariableScope) {
|
|
4
|
+
VariableScope[VariableScope["Any"] = 0] = "Any";
|
|
5
|
+
VariableScope[VariableScope["Local"] = 1] = "Local";
|
|
6
|
+
VariableScope[VariableScope["Global"] = 2] = "Global";
|
|
7
|
+
})(VariableScope || (VariableScope = {}));
|
|
2
8
|
export class StackedStates {
|
|
3
9
|
constructor() {
|
|
4
10
|
this.maps = [];
|
|
11
|
+
this.localIndex = -1;
|
|
5
12
|
this.push();
|
|
6
13
|
}
|
|
14
|
+
fixLocalIndex() {
|
|
15
|
+
this.localIndex = this.maps.length;
|
|
16
|
+
}
|
|
17
|
+
resetLocalIndex() {
|
|
18
|
+
this.localIndex = -1;
|
|
19
|
+
}
|
|
7
20
|
push() {
|
|
8
21
|
this.maps.push(new Map());
|
|
9
22
|
}
|
|
10
23
|
pop() {
|
|
11
24
|
this.maps.pop();
|
|
12
25
|
}
|
|
13
|
-
get(name) {
|
|
14
|
-
for (let i = this.
|
|
26
|
+
get(name, scope) {
|
|
27
|
+
for (let i = (this.localIndex === -1 || scope !== VariableScope.Global
|
|
28
|
+
? this.maps.length
|
|
29
|
+
: Math.min(this.maps.length, this.localIndex)) - 1; i >= (this.localIndex === -1 || scope !== VariableScope.Local ? 0 : this.localIndex); i--) {
|
|
15
30
|
if (this.maps[i].has(name)) {
|
|
16
31
|
return this.maps[i].get(name);
|
|
17
32
|
}
|