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/lib/mesh.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import * as t from "@babel/types";
2
- import { calls, composeOnly, styleOnly } from "./call";
3
- import { ctx } from "./internal";
4
- import { bodyHasJsx } from "./jsx-detect";
5
- import { arrayModel, exprCall, forwardOnlyExpr, mapModel, own, parseCalculateCall, reactiveObject, ref, setModel, } from "./lib";
6
- import { transformJsx } from "./jsx";
2
+ import { calls, composeOnly, styleOnly } from "./call.js";
3
+ import { idIsIValue, memberIsIValue, nodeIsReactiveObject } from "./expression.js";
4
+ import { ctx } from "./internal.js";
5
+ import { transformJsx } from "./jsx.js";
6
+ import { arrayModel, exprCall, forwardOnlyExpr, mapModel, named, own, parseCalculateCall, reactiveObject, ref, setModel, } from "./lib.js";
7
7
  export function meshOrIgnoreAllExpressions(nodePaths, internal) {
8
8
  for (const path of nodePaths) {
9
9
  if (t.isExpression(path.node)) {
@@ -23,12 +23,14 @@ export function meshComposeCall(call, name, nodePath, internal) {
23
23
  }
24
24
  const fnPath = nodePath.get("arguments")[0];
25
25
  compose(fnPath, internal, false);
26
- arg.params.unshift(ctx);
27
- if (t.isArrowFunctionExpression(arg) && internal.devMode) {
28
- fnPath.replaceWith(t.functionExpression(t.identifier(internal.prefix + (name ? name.name : "Default")), arg.params, t.isBlockStatement(arg.body) ? arg.body : t.blockStatement([t.returnStatement(arg.body)]), false, arg.async));
26
+ if (!internal.stateOnly) {
27
+ arg.params.unshift(ctx);
29
28
  }
30
- else if (t.isFunctionExpression(arg) && name && internal.devMode) {
31
- arg.id = t.identifier(internal.prefix + name.name);
29
+ if (internal.devMode) {
30
+ call.arguments.push(t.stringLiteral(`${internal.prefix}:${name ? name.name : "#anonymouse"}`));
31
+ }
32
+ if (t.isIdentifier(call.callee) && call.callee.name === "state") {
33
+ nodePath.replaceWith(call.arguments[0]);
32
34
  }
33
35
  }
34
36
  export function meshAllUnknown(paths, internal) {
@@ -43,26 +45,21 @@ export function meshAllUnknown(paths, internal) {
43
45
  }
44
46
  export function meshLValue(path, internal) {
45
47
  const node = path.node;
46
- if (t.isArrayPattern(node) ||
47
- t.isObjectPattern(node) ||
48
- t.isTSParameterProperty(node) ||
49
- t.isAssignmentPattern(node) ||
50
- t.isRestElement(node)) {
51
- return;
48
+ if (t.isExpression(node)) {
49
+ meshExpression(path, internal);
52
50
  }
53
- meshExpression(path, internal);
54
51
  }
55
52
  export function meshOrIgnoreExpression(path, internal) {
56
53
  if (t.isExpression(path.node)) {
57
54
  meshExpression(path, internal);
58
55
  }
59
56
  }
60
- export function meshExpression(nodePath, internal) {
57
+ export function meshExpression(nodePath, internal, isRoot) {
61
58
  const expr = nodePath.node;
62
59
  if (!expr) {
63
60
  return;
64
61
  }
65
- if (calls(expr, ["compose", "extend"], internal)) {
62
+ if (calls(expr, ["compose", "extend", "state"], internal)) {
66
63
  meshComposeCall(expr, null, nodePath, internal);
67
64
  return;
68
65
  }
@@ -79,11 +76,8 @@ export function meshExpression(nodePath, internal) {
79
76
  }
80
77
  case "Identifier": {
81
78
  const state = internal.stack.get(expr.name);
82
- if (state === 2 /* VariableState.Reactive */) {
83
- nodePath.replaceWith(t.memberExpression(expr, t.identifier("$")));
84
- }
85
- else if (state === 4 /* VariableState.ReactivePointer */) {
86
- nodePath.replaceWith(t.memberExpression(expr, t.identifier("$$")));
79
+ if (idIsIValue(nodePath, internal)) {
80
+ nodePath.replaceWith(t.memberExpression(expr, t.identifier(state === 4 /* VariableState.ReactivePointer */ ? "$$" : "$")));
87
81
  }
88
82
  break;
89
83
  }
@@ -92,50 +86,43 @@ export function meshExpression(nodePath, internal) {
92
86
  meshAllUnknown(path.get("elements"), internal);
93
87
  break;
94
88
  }
95
- case "TupleExpression": {
96
- const path = nodePath;
97
- meshAllUnknown(path.get("elements"), internal);
98
- break;
99
- }
100
89
  case "CallExpression":
101
90
  case "OptionalCallExpression": {
102
91
  const path = nodePath;
103
92
  const callsFn = calls(path.node, composeOnly, internal);
104
93
  const callsStyleHint = calls(path.node, styleOnly, internal);
105
- const callsStyleCreate = calls(path.node, ["webStyleSheet"], internal);
106
94
  if (callsFn) {
107
95
  throw path.buildCodeFrameError(`Vasille: Usage of hint "${callsFn}" is restricted here`);
108
96
  }
109
97
  if (callsStyleHint) {
110
98
  throw path.buildCodeFrameError(`Vasille: Usage of style hint "${callsStyleHint}" is restricted here`);
111
99
  }
112
- if (callsStyleCreate) {
113
- throw path.buildCodeFrameError("Vasille: Styles can be created in moldule level code only");
114
- }
115
100
  meshOrIgnoreExpression(path.get("callee"), internal);
116
101
  meshAllUnknown(path.get("arguments"), internal);
117
102
  if (calls(path.node, ["calculate"], internal)) {
118
- if (path.node.arguments.length !== 1 && !t.isExpression(path.node.arguments[0])) {
103
+ if (path.node.arguments.length === 1 &&
104
+ (t.isFunctionExpression(path.node.arguments[0]) || t.isArrowFunctionExpression(path.node.arguments[0]))) {
105
+ path.replaceWith(t.callExpression(path.node.arguments[0], []));
106
+ }
107
+ else {
119
108
  throw path.buildCodeFrameError("Vasille: Incorrect calculate argument");
120
109
  }
121
- path.replaceWith(t.callExpression(path.node.arguments[0], []));
122
110
  }
123
111
  break;
124
112
  }
125
113
  case "AssignmentExpression": {
126
114
  const path = nodePath;
127
115
  const left = path.node.left;
116
+ let replaced = false;
128
117
  meshLValue(path.get("left"), internal);
129
118
  if (t.isIdentifier(left) && internal.stack.get(left.name) === 4 /* VariableState.ReactivePointer */) {
130
119
  const replaceWith = forwardOnlyExpr(path.get("right"), path.node.right, internal);
131
120
  if (replaceWith) {
132
121
  path.get("right").replaceWith(replaceWith);
133
- }
134
- else {
135
- meshExpression(path.get("right"), internal);
122
+ replaced = true;
136
123
  }
137
124
  }
138
- else {
125
+ if (!replaced) {
139
126
  meshExpression(path.get("right"), internal);
140
127
  }
141
128
  break;
@@ -149,7 +136,7 @@ export function meshExpression(nodePath, internal) {
149
136
  if (t.isExpression(property) && !t.isIdentifier(property)) {
150
137
  meshOrIgnoreExpression(path.get("property"), internal);
151
138
  }
152
- if (t.isIdentifier(node.object) && internal.stack.get(node.object.name) === 3 /* VariableState.ReactiveObject */) {
139
+ if (memberIsIValue(node, internal)) {
153
140
  path.replaceWith(t.memberExpression(node, t.identifier("$")));
154
141
  }
155
142
  break;
@@ -184,11 +171,6 @@ export function meshExpression(nodePath, internal) {
184
171
  meshAllExpressions(path.get("expressions"), internal);
185
172
  break;
186
173
  }
187
- case "ParenthesizedExpression": {
188
- const path = nodePath;
189
- meshExpression(path.get("expression"), internal);
190
- break;
191
- }
192
174
  case "UnaryExpression": {
193
175
  const path = nodePath;
194
176
  meshExpression(path.get("argument"), internal);
@@ -209,27 +191,6 @@ export function meshExpression(nodePath, internal) {
209
191
  meshExpression(path.get("argument"), internal);
210
192
  break;
211
193
  }
212
- case "TypeCastExpression": {
213
- const path = nodePath;
214
- meshExpression(path.get("expression"), internal);
215
- break;
216
- }
217
- case "BindExpression": {
218
- const path = nodePath;
219
- meshExpression(path.get("callee"), internal);
220
- meshExpression(path.get("object"), internal);
221
- break;
222
- }
223
- case "PipelineTopicExpression": {
224
- const path = nodePath;
225
- meshExpression(path.get("expression"), internal);
226
- break;
227
- }
228
- case "PipelineBareFunction": {
229
- const path = nodePath;
230
- meshExpression(path.get("callee"), internal);
231
- break;
232
- }
233
194
  case "TSInstantiationExpression": {
234
195
  const path = nodePath;
235
196
  meshExpression(path.get("expression"), internal);
@@ -257,16 +218,38 @@ export function meshExpression(nodePath, internal) {
257
218
  if (t.isObjectProperty(prop)) {
258
219
  const path = propPath;
259
220
  const valuePath = path.get("value");
260
- if (valuePath instanceof Array) {
261
- meshAllExpressions(valuePath, internal);
221
+ let replaced = false;
222
+ if (isRoot &&
223
+ internal.stateOnly &&
224
+ !path.node.computed &&
225
+ t.isIdentifier(path.node.key) &&
226
+ t.isExpression(valuePath.node)) {
227
+ const call = exprCall(valuePath, valuePath.node, internal);
228
+ if (call) {
229
+ if (path.node.key.name.startsWith("$")) {
230
+ valuePath.replaceWith(call);
231
+ }
232
+ else {
233
+ throw path.buildCodeFrameError("Vasille: Reactive value property name must start with $");
234
+ }
235
+ replaced = true;
236
+ }
237
+ else if (t.isIdentifier(valuePath.node) &&
238
+ internal.stack.get(valuePath.node.name) === 3 /* VariableState.ReactiveObject */ &&
239
+ !path.node.key.name.startsWith("$$")) {
240
+ throw path.buildCodeFrameError("Vasille: Reactive object property name must start with $$");
241
+ }
262
242
  }
263
- else {
243
+ if (!replaced) {
264
244
  meshOrIgnoreExpression(valuePath, internal);
265
245
  }
266
246
  }
267
247
  else if (t.isObjectMethod(prop)) {
268
248
  meshFunction(propPath, internal);
269
249
  }
250
+ else if (isRoot && internal.stateOnly && t.isSpreadElement(prop)) {
251
+ throw propPath.buildCodeFrameError("Vasille: Spread element is not allowed here");
252
+ }
270
253
  else {
271
254
  meshAllUnknown([propPath], internal);
272
255
  }
@@ -281,41 +264,16 @@ export function meshExpression(nodePath, internal) {
281
264
  meshFunction(nodePath, internal);
282
265
  break;
283
266
  }
267
+ case "ClassExpression": {
268
+ meshClassBody(nodePath.get("body"), internal);
269
+ break;
270
+ }
284
271
  case "JSXFragment": {
285
272
  throw nodePath.buildCodeFrameError("Vasille: JSX fragment is not allowed here");
286
273
  }
287
274
  case "JSXElement": {
288
275
  throw nodePath.buildCodeFrameError("Vasille: JSX element is not allowed here");
289
276
  }
290
- case "BigIntLiteral":
291
- case "BooleanLiteral":
292
- case "ClassExpression":
293
- case "DecimalLiteral":
294
- case "DoExpression":
295
- case "Import":
296
- case "ImportExpression":
297
- case "MetaProperty":
298
- case "ModuleExpression":
299
- case "NullLiteral":
300
- case "NumericLiteral":
301
- case "PipelinePrimaryTopicReference":
302
- case "RecordExpression":
303
- case "RegExpLiteral":
304
- case "StringLiteral":
305
- case "Super":
306
- case "TSNonNullExpression":
307
- case "ThisExpression":
308
- case "TopicReference":
309
- }
310
- }
311
- export function meshBody(path, internal) {
312
- if (t.isExpression(path.node)) {
313
- meshExpression(path, internal);
314
- }
315
- else {
316
- for (const statementPath of path.get("body")) {
317
- meshStatement(statementPath, internal);
318
- }
319
277
  }
320
278
  }
321
279
  export function meshStatements(paths, internal) {
@@ -331,14 +289,7 @@ export function ignoreParams(val, internal) {
331
289
  internal.stack.set(val.name, 1 /* VariableState.Ignored */);
332
290
  }
333
291
  else if (t.isObjectPattern(val)) {
334
- for (const prop of val.properties) {
335
- if (t.isObjectProperty(prop) && t.isIdentifier(prop.value)) {
336
- internal.stack.set(prop.value.name, 1 /* VariableState.Ignored */);
337
- }
338
- else if (t.isRestElement(prop) && t.isIdentifier(prop.argument)) {
339
- internal.stack.set(prop.argument.name, 1 /* VariableState.Ignored */);
340
- }
341
- }
292
+ ignoreObjectPattern(val, internal);
342
293
  }
343
294
  else if (t.isArrayPattern(val)) {
344
295
  for (const element of val.elements) {
@@ -348,28 +299,70 @@ export function ignoreParams(val, internal) {
348
299
  }
349
300
  }
350
301
  }
351
- export function reactiveArrayPattern(expr, internal) {
352
- if (t.isArrayPattern(expr)) {
353
- for (const element of expr.elements) {
354
- if (t.isIdentifier(element)) {
355
- internal.stack.set(element.name, 2 /* VariableState.Reactive */);
302
+ function ignoreObjectPattern(pattern, internal) {
303
+ for (const property of pattern.properties) {
304
+ if (t.isObjectProperty(property)) {
305
+ if (t.isObjectPattern(property.value)) {
306
+ ignoreObjectPattern(property.value, internal);
307
+ }
308
+ else if (t.isAssignmentPattern(property.value)) {
309
+ ignoreParams(property.value, internal);
356
310
  }
311
+ else if (t.isIdentifier(property.value)) {
312
+ internal.stack.set(property.value.name, 1 /* VariableState.Ignored */);
313
+ }
314
+ }
315
+ if (t.isRestElement(property)) {
316
+ internal.stack.set(property.argument.name, 1 /* VariableState.Ignored */);
357
317
  }
358
318
  }
359
- else if (t.isIdentifier(expr)) {
360
- internal.stack.set(expr.name, 3 /* VariableState.ReactiveObject */);
319
+ }
320
+ export function reactiveArrayPattern(path, internal) {
321
+ if (t.isArrayPattern(path.node)) {
322
+ path.node.elements.forEach((element, index) => {
323
+ if (t.isIdentifier(element)) {
324
+ internal.stack.set(element.name, index < 2 ? 2 /* VariableState.Reactive */ : 1 /* VariableState.Ignored */);
325
+ }
326
+ });
361
327
  }
362
328
  else {
363
- return false;
329
+ throw path.buildCodeFrameError("Vasille: Expected array pattern");
330
+ }
331
+ }
332
+ function meshForEachHeader(path, internal) {
333
+ const left = path.node.left;
334
+ meshExpression(path.get("right"), internal);
335
+ if (t.isVariableDeclaration(left) && t.isVariableDeclarator(left.declarations[0])) {
336
+ ignoreParams(left.declarations[0].id, internal);
337
+ }
338
+ }
339
+ function meshForHeader(path, internal) {
340
+ const node = path.node;
341
+ if (node.init) {
342
+ if (t.isExpression(node.init)) {
343
+ meshExpression(path.get("init"), internal);
344
+ }
345
+ else {
346
+ const variablePath = path.get("init");
347
+ for (const declarationPath of variablePath.get("declarations")) {
348
+ meshExpression(declarationPath.get("init"), internal);
349
+ ignoreParams(declarationPath.node.id, internal);
350
+ }
351
+ }
352
+ }
353
+ meshExpression(path.get("test"), internal);
354
+ meshExpression(path.get("update"), internal);
355
+ }
356
+ function meshClassBody(path, internal) {
357
+ for (const item of path.get("body")) {
358
+ if (t.isClassMethod(item.node) || t.isClassPrivateMethod(item.node)) {
359
+ meshFunction(item, internal);
360
+ }
364
361
  }
365
- return true;
366
362
  }
367
363
  export function meshStatement(path, internal) {
368
364
  const statement = path.node;
369
- if (!statement) {
370
- return;
371
- }
372
- switch (statement.type) {
365
+ switch (statement && statement.type) {
373
366
  case "BlockStatement":
374
367
  internal.stack.push();
375
368
  meshStatements(path.get("body"), internal);
@@ -388,46 +381,24 @@ export function meshStatement(path, internal) {
388
381
  break;
389
382
  case "ForInStatement": {
390
383
  const _path = path;
391
- const left = _path.node.left;
392
384
  internal.stack.push();
393
- meshExpression(_path.get("right"), internal);
394
- if (t.isVariableDeclaration(left) && t.isVariableDeclarator(left.declarations[0])) {
395
- ignoreParams(left.declarations[0].id, internal);
396
- }
385
+ meshForEachHeader(_path, internal);
397
386
  meshStatement(_path.get("body"), internal);
398
387
  internal.stack.pop();
399
388
  break;
400
389
  }
401
390
  case "ForOfStatement": {
402
391
  const _path = path;
403
- const left = _path.node.left;
404
392
  internal.stack.push();
405
- meshExpression(_path.get("right"), internal);
406
- if (t.isVariableDeclaration(left) && t.isVariableDeclarator(left.declarations[0])) {
407
- ignoreParams(left.declarations[0].id, internal);
408
- }
393
+ meshForEachHeader(_path, internal);
409
394
  meshStatement(_path.get("body"), internal);
410
395
  internal.stack.pop();
411
396
  break;
412
397
  }
413
398
  case "ForStatement": {
414
399
  const _path = path;
415
- const node = _path.node;
416
400
  internal.stack.push();
417
- if (node.init) {
418
- if (t.isExpression(node.init)) {
419
- meshExpression(_path.get("init"), internal);
420
- }
421
- else {
422
- const variablePath = _path.get("init");
423
- for (const declarationPath of variablePath.get("declarations")) {
424
- meshExpression(declarationPath.get("init"), internal);
425
- ignoreParams(declarationPath.node.id, internal);
426
- }
427
- }
428
- }
429
- meshExpression(_path.get("test"), internal);
430
- meshExpression(_path.get("update"), internal);
401
+ meshForHeader(_path, internal);
431
402
  meshStatement(_path.get("body"), internal);
432
403
  internal.stack.pop();
433
404
  break;
@@ -468,20 +439,21 @@ export function meshStatement(path, internal) {
468
439
  break;
469
440
  case "TryStatement":
470
441
  meshStatement(path.get("block"), internal);
442
+ if (path.node.handler) {
443
+ meshStatement(path.get("handler").get("body"), internal);
444
+ }
445
+ meshStatement(path.get("finalizer"), internal);
471
446
  break;
472
447
  case "VariableDeclaration": {
473
448
  const _path = path;
474
449
  for (const declaration of _path.get("declarations")) {
475
450
  const expr = declaration.node.init;
476
- let ignore = true;
477
- if (expr && t.isIdentifier(declaration.node.id) && calls(expr, ["compose", "extend"], internal)) {
451
+ if (expr && t.isIdentifier(declaration.node.id) && calls(expr, ["compose", "extend", "state"], internal)) {
478
452
  meshComposeCall(expr, declaration.node.id, declaration.get("init"), internal);
479
453
  }
480
454
  else {
481
455
  meshExpression(declaration.get("init"), internal);
482
- if (ignore) {
483
- ignoreParams(declaration.node.id, internal);
484
- }
456
+ ignoreParams(declaration.node.id, internal);
485
457
  }
486
458
  }
487
459
  break;
@@ -494,49 +466,25 @@ export function meshStatement(path, internal) {
494
466
  internal.stack.pop();
495
467
  break;
496
468
  }
497
- case "WithStatement": {
498
- const _path = path;
499
- meshExpression(_path.get("object"), internal);
500
- internal.stack.push();
501
- meshStatement(_path.get("body"), internal);
502
- internal.stack.pop();
503
- break;
504
- }
505
469
  case "ExportNamedDeclaration": {
506
470
  meshStatement(path.get("declaration"), internal);
507
471
  break;
508
472
  }
509
- // Ignored
510
- case "ExportDefaultDeclaration":
511
- case "ExportAllDeclaration":
512
- case "BreakStatement":
513
- case "ContinueStatement":
514
- case "DebuggerStatement":
515
- case "EmptyStatement":
516
473
  case "ClassDeclaration":
517
- case "ImportDeclaration":
518
- case "DeclareClass":
519
- case "DeclareFunction":
520
- case "DeclareInterface":
521
- case "DeclareModule":
522
- case "DeclareModuleExports":
523
- case "DeclareTypeAlias":
524
- case "DeclareOpaqueType":
525
- case "DeclareVariable":
526
- case "DeclareExportDeclaration":
527
- case "DeclareExportAllDeclaration":
528
- case "InterfaceDeclaration":
529
- case "OpaqueType":
530
- case "TypeAlias":
531
- case "EnumDeclaration":
532
- case "TSDeclareFunction":
533
- case "TSInterfaceDeclaration":
534
- case "TSTypeAliasDeclaration":
535
- case "TSEnumDeclaration":
536
- case "TSModuleDeclaration":
537
- case "TSImportEqualsDeclaration":
538
- case "TSExportAssignment":
539
- case "TSNamespaceExportDeclaration":
474
+ meshClassBody(path.get("body"), internal);
475
+ break;
476
+ case "ExportDefaultDeclaration": {
477
+ const declarationPath = path.get("declaration");
478
+ if (t.isExpression(declarationPath.node)) {
479
+ meshExpression(declarationPath, internal);
480
+ }
481
+ else if (t.isFunctionDeclaration(declarationPath.node)) {
482
+ meshFunction(declarationPath, internal);
483
+ }
484
+ else if (t.isClassDeclaration(declarationPath.node)) {
485
+ meshClassBody(declarationPath.get("body"), internal);
486
+ }
487
+ }
540
488
  }
541
489
  }
542
490
  export function meshFunction(path, internal) {
@@ -560,87 +508,70 @@ export function meshFunction(path, internal) {
560
508
  }
561
509
  internal.stack.pop();
562
510
  }
563
- export function composeExpression(path, internal) {
511
+ export function composeExpression(path, internal, isRoot) {
564
512
  const expr = path.node;
565
- if (!expr) {
566
- return;
567
- }
568
- switch (expr.type) {
513
+ switch (expr && expr.type) {
569
514
  case "AssignmentExpression": {
570
- const assign = expr;
571
- if (calls(assign.right, ["awaited"], internal)) {
572
- reactiveArrayPattern(assign.left, internal);
573
- }
574
- else {
575
- meshExpression(path, internal);
576
- }
515
+ meshExpression(path, internal);
577
516
  break;
578
517
  }
579
518
  case "CallExpression":
580
519
  case "OptionalCallExpression": {
581
520
  const call = expr;
582
- let replaced = false;
583
521
  if (calls(call, ["watch"], internal)) {
584
522
  const args = parseCalculateCall(path, internal);
585
523
  if (args) {
586
- path.replaceWith(t.callExpression(t.memberExpression(ctx, t.identifier("watch")), args));
587
- replaced = true;
588
- }
589
- }
590
- else if (calls(call, ["arrayModel"], internal)) {
591
- const value = call.arguments[0];
592
- if (t.isArrayExpression(value)) {
593
- path.replaceWith(arrayModel(value, internal));
594
- replaced = true;
595
- }
596
- else {
597
- path.buildCodeFrameError(`Vasille: arrayModel requires array expression as argument`);
524
+ if (args[1].elements.length > 0) {
525
+ path.replaceWith(t.callExpression(t.memberExpression(ctx, t.identifier("watch")), args));
526
+ }
527
+ else {
528
+ path.replaceWith(t.callExpression(args[0], []));
529
+ }
598
530
  }
599
531
  }
600
- else if (calls(call, ["mapModel", "setModel"], internal)) {
601
- const args = call.arguments;
602
- const name = calls(call, ["mapModel", "setModel"], internal);
603
- path.replaceWith(name === "mapModel" ? mapModel(args, internal) : setModel(args, internal));
604
- replaced = true;
605
- }
606
- if (!replaced) {
532
+ else {
607
533
  meshExpression(path, internal);
608
534
  }
609
535
  break;
610
536
  }
537
+ case "LogicalExpression":
538
+ composeExpression(path.get("left"), internal);
539
+ composeExpression(path.get("right"), internal);
540
+ break;
541
+ case "ConditionalExpression":
542
+ meshExpression(path.get("test"), internal);
543
+ composeExpression(path.get("consequent"), internal);
544
+ composeExpression(path.get("alternate"), internal);
545
+ break;
611
546
  case "JSXElement":
612
547
  case "JSXFragment":
548
+ if (internal.stateOnly) {
549
+ throw path.buildCodeFrameError("Vasille: JSX is not allowed in states");
550
+ }
613
551
  path.replaceWithMultiple(transformJsx(path, internal));
614
552
  break;
615
553
  default:
616
- meshExpression(path, internal);
554
+ meshExpression(path, internal, isRoot);
617
555
  }
618
556
  }
619
- export function composeStatements(paths, internal) {
557
+ export function composeStatements(paths, internal, isRoot) {
620
558
  for (const path of paths) {
621
- composeStatement(path, internal);
559
+ composeStatement(path, internal, isRoot);
622
560
  }
623
561
  }
624
- export function composeStatement(path, internal) {
562
+ export function composeStatement(path, internal, isRoot) {
625
563
  const statement = path.node;
626
564
  if (!statement) {
627
565
  return;
628
566
  }
629
567
  switch (statement.type) {
630
568
  case "FunctionDeclaration": {
631
- const _path = path;
632
- const fn = _path.node;
633
- if (bodyHasJsx(fn.body)) {
634
- compose(_path, internal, false);
635
- }
636
- else {
637
- meshFunction(_path, internal);
638
- }
569
+ meshFunction(path, internal);
639
570
  break;
640
571
  }
641
572
  case "BlockStatement": {
642
573
  internal.stack.push();
643
- composeStatements(path.get("body"), internal);
574
+ composeStatements(path.get("body"), internal, isRoot);
644
575
  internal.stack.pop();
645
576
  break;
646
577
  }
@@ -658,34 +589,16 @@ export function composeStatement(path, internal) {
658
589
  }
659
590
  case "ForInStatement": {
660
591
  const _path = path;
661
- const left = _path.node.left;
662
592
  internal.stack.push();
663
- meshExpression(_path.get("right"), internal);
664
- if (t.isVariableDeclaration(left) && t.isVariableDeclarator(left.declarations[0])) {
665
- ignoreParams(left.declarations[0].id, internal);
666
- }
593
+ meshForEachHeader(_path, internal);
667
594
  composeStatement(_path.get("body"), internal);
668
595
  internal.stack.pop();
669
596
  break;
670
597
  }
671
598
  case "ForStatement": {
672
599
  const _path = path;
673
- const node = _path.node;
674
600
  internal.stack.push();
675
- if (node.init) {
676
- if (t.isExpression(node.init)) {
677
- meshExpression(_path.get("init"), internal);
678
- }
679
- else {
680
- const variablePath = _path.get("init");
681
- for (const declarationPath of variablePath.get("declarations")) {
682
- meshExpression(declarationPath.get("init"), internal);
683
- ignoreParams(declarationPath.node.id, internal);
684
- }
685
- }
686
- }
687
- meshExpression(_path.get("test"), internal);
688
- meshExpression(_path.get("update"), internal);
601
+ meshForHeader(_path, internal);
689
602
  composeStatement(_path.get("body"), internal);
690
603
  internal.stack.pop();
691
604
  break;
@@ -705,7 +618,7 @@ export function composeStatement(path, internal) {
705
618
  composeStatement(path.get("body"), internal);
706
619
  break;
707
620
  case "ReturnStatement":
708
- composeExpression(path.get("argument"), internal);
621
+ composeExpression(path.get("argument"), internal, isRoot);
709
622
  break;
710
623
  case "SwitchStatement": {
711
624
  const _path = path;
@@ -719,7 +632,10 @@ export function composeStatement(path, internal) {
719
632
  break;
720
633
  }
721
634
  case "TryStatement":
635
+ const tryHandler = path.get("handler");
722
636
  composeStatement(path.get("block"), internal);
637
+ tryHandler.node && composeStatement(tryHandler.get("body"), internal);
638
+ composeStatement(path.get("finalizer"), internal);
723
639
  break;
724
640
  case "VariableDeclaration": {
725
641
  const _path = path;
@@ -731,10 +647,22 @@ export function composeStatement(path, internal) {
731
647
  for (const declaration of _path.get("declarations")) {
732
648
  const id = declaration.node.id;
733
649
  let meshInit = true;
650
+ function idName(target = id) {
651
+ let name = "#";
652
+ if (t.isIdentifier(target)) {
653
+ name = target.name;
654
+ }
655
+ return name;
656
+ }
657
+ function idDoubleName() {
658
+ const pattern = id;
659
+ return [idName(pattern.elements[0]), idName(pattern.elements[1])];
660
+ }
734
661
  ignoreParams(declaration.node.id, internal);
735
662
  if (calls(declaration.node.init, ["awaited"], internal)) {
736
- reactiveArrayPattern(declaration.node.id, internal);
663
+ reactiveArrayPattern(declaration.get("id"), internal);
737
664
  meshAllUnknown(declaration.get("init").get("arguments"), internal);
665
+ named(declaration.node.init, idDoubleName(), internal);
738
666
  meshInit = false;
739
667
  }
740
668
  else if (t.isIdentifier(id)) {
@@ -747,95 +675,109 @@ export function composeStatement(path, internal) {
747
675
  }
748
676
  else if (calls(init, ["bind"], internal)) {
749
677
  const argument = init.arguments[0];
750
- const replaceWith = declares === 2 /* VariableState.Reactive */
751
- ? forwardOnlyExpr(declaration.get("init"), argument, internal)
752
- : exprCall(declaration.get("init"), argument, internal);
753
- let insertNode = replaceWith !== null && replaceWith !== void 0 ? replaceWith : ref(t.isExpression(argument) ? argument : null);
678
+ const argumentPath = declaration.get("init").get("arguments")[0];
679
+ let replaceWith = declares === 2 /* VariableState.Reactive */
680
+ ? forwardOnlyExpr(argumentPath, argument, internal)
681
+ : exprCall(argumentPath, argument, internal, idName());
682
+ if (!replaceWith) {
683
+ replaceWith =
684
+ declares === 2 /* VariableState.Reactive */
685
+ ? t.callExpression(t.memberExpression(internal.id, t.identifier("r")), [argument])
686
+ : ref(argument, internal, idName());
687
+ }
754
688
  if (declares === 2 /* VariableState.Reactive */) {
755
689
  internal.stack.set(id.name, 4 /* VariableState.ReactivePointer */);
756
- insertNode = own(insertNode);
690
+ replaceWith = own(replaceWith, internal, idName());
757
691
  }
758
692
  else {
759
693
  internal.stack.set(id.name, 2 /* VariableState.Reactive */);
760
694
  }
761
- declaration.get("init").replaceWith(insertNode);
695
+ declaration.get("init").replaceWith(replaceWith);
762
696
  meshInit = !replaceWith;
763
697
  }
764
698
  else if (calls(init, ["ref"], internal)) {
765
699
  const argument = init.arguments[0];
766
700
  internal.stack.set(id.name, 2 /* VariableState.Reactive */);
767
- declaration.get("init").replaceWith(ref(t.isExpression(argument) ? argument : null));
701
+ declaration.get("init").replaceWith(ref(t.isExpression(argument) ? argument : null, internal, idName()));
768
702
  }
769
703
  else if (calls(init, ["reactiveObject"], internal)) {
770
704
  const value = init.arguments[0];
771
705
  if (kind !== "const") {
772
- declaration.buildCodeFrameError(`Vasille: Reactive objects must be must be declared as constants`);
706
+ throw declaration.buildCodeFrameError(`Vasille: Reactive objects must be must be declared as constants`);
773
707
  }
774
708
  if (t.isObjectExpression(value)) {
775
- declaration.get("init").replaceWith(reactiveObject(value, internal));
709
+ declaration.get("init").replaceWith(reactiveObject(value, internal, idName()));
776
710
  internal.stack.set(id.name, 3 /* VariableState.ReactiveObject */);
777
711
  }
778
712
  else {
779
- declaration.buildCodeFrameError(`Vasille: reactiveObject requires object expression as argument`);
713
+ throw declaration.buildCodeFrameError(`Vasille: reactiveObject requires object expression as argument`);
780
714
  }
781
715
  }
782
716
  else if (calls(init, ["arrayModel"], internal)) {
783
717
  const value = init.arguments[0];
784
718
  if (kind !== "const") {
785
- declaration.buildCodeFrameError(`Vasille: Array models must be must be declared as constants`);
719
+ throw declaration.buildCodeFrameError(`Vasille: Array models must be must be declared as constants`);
786
720
  }
787
721
  if (t.isArrayExpression(value)) {
788
- declaration.get("init").replaceWith(arrayModel(value, internal));
722
+ declaration.get("init").replaceWith(arrayModel(value, internal, idName()));
789
723
  }
790
724
  else {
791
- declaration.buildCodeFrameError(`Vasille: arrayModel requires array expression as argument`);
725
+ declaration.get("init").replaceWith(arrayModel(null, internal, idName()));
792
726
  }
793
727
  }
794
728
  else if (calls(init, ["mapModel", "setModel"], internal)) {
795
729
  const args = init.arguments;
796
730
  const name = calls(init, ["mapModel", "setModel"], internal);
797
731
  if (kind !== "const") {
798
- declaration.buildCodeFrameError(`Vasille: ${name === "mapModel" ? "Map" : "Set"} models must be declared as constants`);
732
+ throw declaration.buildCodeFrameError(`Vasille: ${name === "mapModel" ? "Map" : "Set"} models must be declared as constants`);
799
733
  }
800
734
  declaration
801
735
  .get("init")
802
- .replaceWith(name === "mapModel" ? mapModel(args, internal) : setModel(args, internal));
736
+ .replaceWith(name === "mapModel" ? mapModel(args, internal, idName()) : setModel(args, internal, idName()));
803
737
  }
804
738
  else if (t.isObjectExpression(init)) {
805
739
  if (kind !== "const") {
806
- declaration.buildCodeFrameError(`Vasille: Objects must be must be declared as constants`);
740
+ throw declaration.buildCodeFrameError(`Vasille: Objects must be must be declared as constants`);
807
741
  }
808
- declaration.get("init").replaceWith(reactiveObject(init, internal));
742
+ declaration.get("init").replaceWith(reactiveObject(init, internal, idName()));
809
743
  internal.stack.set(id.name, 3 /* VariableState.ReactiveObject */);
810
744
  }
811
745
  else if (t.isArrayExpression(init)) {
812
746
  if (kind !== "const") {
813
- declaration.buildCodeFrameError(`Vasille: Arrays must be must be declared as constants`);
747
+ throw declaration.buildCodeFrameError(`Vasille: Arrays must be must be declared as constants`);
814
748
  }
815
- declaration.get("init").replaceWith(arrayModel(init, internal));
749
+ declaration.get("init").replaceWith(arrayModel(init, internal, idName()));
816
750
  }
817
751
  else if (t.isNewExpression(init) && t.isIdentifier(init.callee)) {
818
752
  if (init.callee.name === "Map" || init.callee.name === "Set") {
819
753
  if (kind !== "const") {
820
- declaration.buildCodeFrameError(`Vasille: ${init.callee.name === "Map" ? "Maps" : "Sets"} must be declared as constants`);
754
+ throw declaration.buildCodeFrameError(`Vasille: ${init.callee.name === "Map" ? "Maps" : "Sets"} must be declared as constants`);
821
755
  }
822
756
  declaration
823
757
  .get("init")
824
- .replaceWith(init.callee.name === "Map" ? mapModel(init.arguments, internal) : setModel(init.arguments, internal));
758
+ .replaceWith(init.callee.name === "Map"
759
+ ? mapModel(init.arguments, internal, idName())
760
+ : setModel(init.arguments, internal, idName()));
825
761
  }
826
762
  }
827
763
  else if (declares === 2 /* VariableState.Reactive */) {
828
764
  const replaceWith = forwardOnlyExpr(declaration.get("init"), declaration.node.init, internal);
829
765
  meshInit = !replaceWith;
830
766
  internal.stack.set(id.name, replaceWith ? 4 /* VariableState.ReactivePointer */ : 2 /* VariableState.Reactive */);
831
- declaration.get("init").replaceWith(replaceWith ? own(replaceWith) : ref(declaration.node.init));
767
+ declaration
768
+ .get("init")
769
+ .replaceWith(replaceWith ? own(replaceWith, internal, idName()) : ref(declaration.node.init, internal, idName()));
832
770
  }
833
771
  else {
834
- const replaceWith = exprCall(declaration.get("init"), declaration.node.init, internal);
772
+ const replaceWith = exprCall(declaration.get("init"), declaration.node.init, internal, idName());
835
773
  if (replaceWith) {
836
774
  declaration.get("init").replaceWith(replaceWith);
837
775
  }
838
- internal.stack.set(id.name, replaceWith ? 2 /* VariableState.Reactive */ : 1 /* VariableState.Ignored */);
776
+ internal.stack.set(id.name, replaceWith
777
+ ? 2 /* VariableState.Reactive */
778
+ : nodeIsReactiveObject(declaration.get("init"), internal)
779
+ ? 3 /* VariableState.ReactiveObject */
780
+ : 1 /* VariableState.Ignored */);
839
781
  meshInit = !replaceWith;
840
782
  }
841
783
  }
@@ -853,17 +795,10 @@ export function composeStatement(path, internal) {
853
795
  internal.stack.pop();
854
796
  break;
855
797
  }
856
- case "WithStatement": {
857
- throw path.buildCodeFrameError("Vasille: Usage of 'with' in components is restricted");
858
- }
859
798
  case "ForOfStatement": {
860
799
  const _path = path;
861
- const left = _path.node.left;
862
800
  internal.stack.push();
863
- meshExpression(_path.get("right"), internal);
864
- if (t.isVariableDeclaration(left) && t.isVariableDeclarator(left.declarations[0])) {
865
- ignoreParams(left.declarations[0].id, internal);
866
- }
801
+ meshForEachHeader(_path, internal);
867
802
  composeStatement(_path.get("body"), internal);
868
803
  internal.stack.pop();
869
804
  break;
@@ -873,9 +808,6 @@ export function composeStatement(path, internal) {
873
808
  }
874
809
  }
875
810
  export function compose(path, internal, isInternalSlot) {
876
- if (t.isFunctionDeclaration(path.node) && path.node.id) {
877
- internal.stack.set(path.node.id.name, 1 /* VariableState.Ignored */);
878
- }
879
811
  internal.stack.push();
880
812
  const node = path.node;
881
813
  const params = node.params;
@@ -883,50 +815,57 @@ export function compose(path, internal, isInternalSlot) {
883
815
  if (t.isFunctionExpression(node) && node.id) {
884
816
  internal.stack.set(node.id.name, 1 /* VariableState.Ignored */);
885
817
  }
886
- if (params.length > 1) {
887
- throw path.get("params")[1].buildCodeFrameError("Vasille: JSX compoent must have no more then 1 parameter");
818
+ if (params.length > 1 && !isInternalSlot) {
819
+ throw path.get("params")[1].buildCodeFrameError("Vasille: JSX component must have no more then 1 parameter");
888
820
  }
889
- for (const param of params) {
890
- const target = t.isAssignmentPattern(param) ? param.left : param;
891
- if (t.isIdentifier(target)) {
892
- internal.stack.set(target.name, isInternalSlot ? 1 /* VariableState.Ignored */ : 3 /* VariableState.ReactiveObject */);
821
+ for (const param of path.get("params")) {
822
+ const node = param.node;
823
+ if (t.isAssignmentPattern(node)) {
824
+ throw param.buildCodeFrameError("Vasille: No default value allowed here");
893
825
  }
894
- else if (t.isObjectPattern(target)) {
895
- for (const prop of target.properties) {
896
- if (t.isObjectProperty(prop)) {
897
- if (t.isIdentifier(prop.value)) {
898
- internal.stack.set(prop.value.name, isInternalSlot ? 1 /* VariableState.Ignored */ : 2 /* VariableState.Reactive */);
826
+ if (t.isIdentifier(node)) {
827
+ internal.stack.set(node.name, isInternalSlot ? 1 /* VariableState.Ignored */ : 3 /* VariableState.ReactiveObject */);
828
+ }
829
+ else if (isInternalSlot && t.isObjectPattern(node)) {
830
+ ignoreObjectPattern(node, internal);
831
+ }
832
+ else if (t.isObjectPattern(node)) {
833
+ for (const prop of param.get("properties")) {
834
+ const node = prop.node;
835
+ if (t.isObjectProperty(node)) {
836
+ const key = node.key;
837
+ let keyName = "";
838
+ if (t.isIdentifier(node.value)) {
839
+ keyName = node.value.name;
840
+ }
841
+ else if (t.isIdentifier(key) && !node.computed) {
842
+ keyName = key.name;
899
843
  }
900
- else if (t.isIdentifier(prop.key)) {
901
- internal.stack.set(prop.key.name, isInternalSlot ? 1 /* VariableState.Ignored */ : 2 /* VariableState.Reactive */);
844
+ internal.stack.set(keyName, 2 /* VariableState.Reactive */);
845
+ if (t.isAssignmentPattern(node.value)) {
846
+ const assignPath = prop.get("value");
847
+ assignPath
848
+ .get("right")
849
+ .replaceWith(t.callExpression(t.memberExpression(internal.id, t.identifier("r")), [assignPath.node.right]));
850
+ }
851
+ else if (!t.isIdentifier(node.value)) {
852
+ throw prop.buildCodeFrameError("Vasille: Value decomposition is not allowed here");
902
853
  }
903
854
  }
904
- else if (t.isRestElement(prop) && t.isIdentifier(prop.argument)) {
905
- internal.stack.set(prop.argument.name, isInternalSlot ? 1 /* VariableState.Ignored */ : 3 /* VariableState.ReactiveObject */);
855
+ if (t.isRestElement(node)) {
856
+ internal.stack.set(node.argument.name, 3 /* VariableState.ReactiveObject */);
906
857
  }
907
858
  }
908
859
  }
909
860
  else {
910
- throw path.get("params")[0].buildCodeFrameError("Vasille: Parameter must be an identifier of object pattern");
911
- }
912
- }
913
- for (const param of path.get("params")) {
914
- if (t.isObjectPattern(param.node)) {
915
- for (const prop of param.get("properties")) {
916
- if (t.isObjectProperty(prop.node) && t.isAssignmentPattern(prop.node.value)) {
917
- const assignPath = prop.get("value");
918
- assignPath
919
- .get("right")
920
- .replaceWith(t.callExpression(t.memberExpression(internal.id, t.identifier("r")), [assignPath.node.right]));
921
- }
922
- }
861
+ throw param.buildCodeFrameError("Vasille: Expected identifier or object pattern");
923
862
  }
924
863
  }
925
864
  if (t.isExpression(body)) {
926
- composeExpression(path.get("body"), internal);
865
+ composeExpression(path.get("body"), internal, true);
927
866
  }
928
867
  else if (t.isBlockStatement(body)) {
929
- composeStatement(path.get("body"), internal);
868
+ composeStatement(path.get("body"), internal, true);
930
869
  }
931
870
  internal.stack.pop();
932
871
  }