babel-plugin-vasille 0.99.5 → 3.1.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/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
- * [ ] `100%` Test Coverage fot babel plugin.
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
- * [ ] Develop dev-tools extension for debugging.
111
- * [ ] Develop a lot of libraries for the framework.
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
- "webStyleSheet",
23
+ "styleSheet",
23
24
  ];
24
- export const requiresContext = ["awaited", "forward"];
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
- const cssGlobal = internal.stack.get(internal.cssGlobal) === undefined;
42
- if (!global && !cssGlobal) {
43
- return;
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(callee.object.name) && t.isCallExpression(node)) {
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;
@@ -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 suppored here");
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: Theme seem the be defined twince");
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: Theme seem the be defined twince");
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: Exprected expression");
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 suppored here");
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: Incompaible key, exprect idenifier or string literal");
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 inly in the root of style");
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: Exprected object expression");
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 restriced");
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: Exprected object expression");
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, ["webStyleSheet"], internal)) {
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: webStyleSheet function has 1 parameter");
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: expected object expression");
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: Exprected object expression");
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 { StackedStates } from "./internal";
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
- if (t.isIdentifier(node)) {
14
- return node.name;
15
- }
14
+ let name = "";
16
15
  if (t.isStringLiteral(node)) {
17
- return node.value;
16
+ name = node.value;
18
17
  }
19
18
  if (t.isPrivateName(node)) {
20
- return node.id.name;
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) && search.stack.get(it.name) === 1 /* VariableState.Ignored */) {
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
- const state = internal.stack.get(path.node.name);
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 (t.isIdentifier(path.node.object) && internal.stack.get(path.node.object.name) === 3 /* VariableState.ReactiveObject */) {
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
- if (t.isIdentifier(path.node)) {
102
+ const node = path.node;
103
+ if (t.isIdentifier(node)) {
68
104
  meshIdentifier(path, internal);
69
105
  }
70
- else if (t.isMemberExpression(path.node) || t.isOptionalMemberExpression(path.node)) {
106
+ else if (t.isMemberExpression(node) || t.isOptionalMemberExpression(node)) {
71
107
  meshMember(path, internal);
72
108
  }
73
- else {
74
- path.traverse({
75
- Identifier(path) {
76
- meshIdentifier(path, internal);
77
- },
78
- MemberExpression(path) {
79
- meshMember(path, internal);
80
- },
81
- OptionalMemberExpression(path) {
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: new StackedStates(),
125
+ stack: internal.stack,
93
126
  };
94
127
  if (t.isIdentifier(path.node)) {
95
- const state = internal.stack.get(path.node.name);
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 (t.isIdentifier(path.node.object) &&
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 chekOrIgnoreExpression(path, search) {
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
- if (!expr) {
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 (search.stack.get(expr.name) !== 1 /* VariableState.Ignored */) {
162
- if (search.external.stack.get(expr.name) === 2 /* VariableState.Reactive */) {
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
- chekOrIgnoreExpression(path.get("callee"), search);
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
- checkExpression(path.get("object"), search);
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
- chekOrIgnoreExpression(path.get("left"), search);
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
- chekOrIgnoreExpression(path.get("callee"), search);
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
- checkExpression(path.get("argument"), search);
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 (valuePath instanceof Array) {
314
- checkAllExpressions(valuePath, search);
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
- ignoreLocals(declarator.id, search);
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
@@ -1,4 +1,4 @@
1
- import { trProgram } from "./transformer";
1
+ import { trProgram } from "./transformer.js";
2
2
  export default function () {
3
3
  return {
4
4
  name: "Vasille",
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.maps.length - 1; i >= 0; i--) {
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
  }