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