babel-plugin-vasille 3.1.5 → 4.0.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
@@ -43,6 +43,7 @@ exports.meshExpression = meshExpression;
43
43
  exports.meshStatements = meshStatements;
44
44
  exports.ignoreParams = ignoreParams;
45
45
  exports.reactiveArrayPattern = reactiveArrayPattern;
46
+ exports.processObjectExpression = processObjectExpression;
46
47
  exports.meshStatement = meshStatement;
47
48
  exports.meshFunction = meshFunction;
48
49
  exports.composeExpression = composeExpression;
@@ -55,9 +56,13 @@ const expression_js_1 = require("./expression.js");
55
56
  const internal_js_1 = require("./internal.js");
56
57
  const jsx_js_1 = require("./jsx.js");
57
58
  const lib_js_1 = require("./lib.js");
59
+ const order_check_1 = require("./order-check");
60
+ const router_1 = require("./router");
61
+ const utils_1 = require("./utils");
58
62
  function meshOrIgnoreAllExpressions(nodePaths, internal) {
59
63
  for (const path of nodePaths) {
60
- if (t.isExpression(path.node)) {
64
+ /* istanbul ignore else */
65
+ if (path.isExpression()) {
61
66
  meshExpression(path, internal);
62
67
  }
63
68
  }
@@ -67,50 +72,46 @@ function meshAllExpressions(nodePaths, internal) {
67
72
  meshExpression(path, internal);
68
73
  }
69
74
  }
70
- function meshComposeCall(call, name, nodePath, internal) {
71
- const arg = call.arguments[0];
72
- if (call.arguments.length !== 1 || !(t.isFunctionExpression(arg) || t.isArrowFunctionExpression(arg))) {
73
- throw nodePath.buildCodeFrameError("Vasille: Invalid arguments");
75
+ function meshComposeCall(name, path, internal) {
76
+ const args = path.isCallExpression() && path.get("arguments");
77
+ const arg = args && (args[0].isFunctionExpression() || args[0].isArrowFunctionExpression()) && args[0];
78
+ if (!args || !arg || args.length !== 1) {
79
+ return (0, lib_js_1.err)(lib_js_1.Errors.IncorrectArguments, path, "Invalid arguments number", internal);
74
80
  }
75
- const fnPath = nodePath.get("arguments")[0];
76
- compose(fnPath, internal, false);
77
- if (!internal.stateOnly) {
78
- arg.params.unshift(internal_js_1.ctx);
79
- }
80
- if (internal.devMode) {
81
- call.arguments.push(t.stringLiteral(`${internal.prefix}:${name ? name.name : "#anonymouse"}`));
81
+ compose(arg, internal, false, false);
82
+ arg.node.params.unshift(internal_js_1.ctx);
83
+ if (internal.devMode && path.isCallExpression()) {
84
+ path.node.arguments.push(t.stringLiteral(name ? name : "#"));
82
85
  }
83
86
  }
84
87
  function meshAllUnknown(paths, internal) {
85
88
  for (const path of paths) {
86
- if (t.isSpreadElement(path.node)) {
89
+ /* istanbul ignore else */
90
+ if (path.isSpreadElement()) {
87
91
  meshExpression(path.get("argument"), internal);
88
92
  }
89
- else if (t.isExpression(path.node)) {
93
+ else if (path.isExpression()) {
90
94
  meshExpression(path, internal);
91
95
  }
92
96
  }
93
97
  }
94
98
  function meshLValue(path, internal) {
95
- const node = path.node;
96
- if (t.isExpression(node)) {
99
+ /* istanbul ignore else */
100
+ if (path.isExpression() || path.isIdentifier()) {
97
101
  meshExpression(path, internal);
98
102
  }
99
103
  }
100
104
  function meshOrIgnoreExpression(path, internal) {
101
- if (t.isExpression(path.node)) {
105
+ /* istanbul ignore else */
106
+ if (path.isExpression()) {
102
107
  meshExpression(path, internal);
103
108
  }
104
109
  }
105
- function meshExpression(nodePath, internal, isRoot) {
110
+ function meshExpression(nodePath, internal) {
106
111
  const expr = nodePath.node;
107
112
  if (!expr) {
108
113
  return;
109
114
  }
110
- if ((0, call_js_1.calls)(expr, ["compose", "store"], internal)) {
111
- meshComposeCall(expr, null, nodePath, internal);
112
- return;
113
- }
114
115
  switch (expr.type) {
115
116
  case "TemplateLiteral": {
116
117
  const path = nodePath;
@@ -123,9 +124,8 @@ function meshExpression(nodePath, internal, isRoot) {
123
124
  break;
124
125
  }
125
126
  case "Identifier": {
126
- const state = internal.stack.get(expr.name);
127
- if ((0, expression_js_1.idIsIValue)(nodePath, internal)) {
128
- nodePath.replaceWith(t.memberExpression(expr, t.identifier(state === 4 /* VariableState.ReactivePointer */ ? "$$" : "$")));
127
+ if ((0, expression_js_1.idIsIValue)(nodePath)) {
128
+ nodePath.replaceWith(t.memberExpression(expr, t.identifier("V")));
129
129
  }
130
130
  break;
131
131
  }
@@ -137,41 +137,84 @@ function meshExpression(nodePath, internal, isRoot) {
137
137
  case "CallExpression":
138
138
  case "OptionalCallExpression": {
139
139
  const path = nodePath;
140
- const callsFn = (0, call_js_1.calls)(path.node, call_js_1.composeOnly, internal);
141
- const callsStyleHint = (0, call_js_1.calls)(path.node, call_js_1.styleOnly, internal);
142
- if (callsFn) {
143
- throw path.buildCodeFrameError(`Vasille: Usage of hint "${callsFn}" is restricted here`);
140
+ const argPath = path.get("arguments")[0];
141
+ // compose call
142
+ if (!internal.isComposing && (0, call_js_1.calls)(nodePath, ["page"], internal)) {
143
+ const firstArg = nodePath.node.typeParameters?.params[0];
144
+ const string = t.isTSLiteralType(firstArg) && t.isStringLiteral(firstArg.literal) && firstArg.literal.value;
145
+ if (string && !internal.filename.replace(/\.[tj]sx?$/, "").endsWith(string)) {
146
+ (0, lib_js_1.err)(lib_js_1.Errors.RulesOfVasille, nodePath.get("typeParameters"), "Page path does not match the file path", internal);
147
+ }
148
+ meshComposeCall(null, nodePath, internal);
144
149
  }
145
- if (callsStyleHint) {
146
- throw path.buildCodeFrameError(`Vasille: Usage of style hint "${callsStyleHint}" is restricted here`);
150
+ else if (!internal.isComposing && (0, call_js_1.calls)(nodePath, call_js_1.composeFunctions, internal)) {
151
+ meshComposeCall(null, nodePath, internal);
147
152
  }
148
- meshOrIgnoreExpression(path.get("callee"), internal);
149
- meshAllUnknown(path.get("arguments"), internal);
150
- if ((0, call_js_1.calls)(path.node, ["calculate"], internal)) {
151
- if (path.node.arguments.length === 1 &&
152
- (t.isFunctionExpression(path.node.arguments[0]) || t.isArrowFunctionExpression(path.node.arguments[0]))) {
153
- path.replaceWith(t.callExpression(path.node.arguments[0], []));
153
+ // raw call
154
+ else if ((0, call_js_1.calls)(path, ["raw"], internal)) {
155
+ if (argPath && argPath.isExpression()) {
156
+ meshExpression(argPath, internal);
157
+ path.replaceWith(argPath);
154
158
  }
155
159
  else {
156
- throw path.buildCodeFrameError("Vasille: Incorrect calculate argument");
160
+ (0, lib_js_1.err)(lib_js_1.Errors.IncorrectArguments, argPath ?? path, "Failed to parse raw value", internal);
161
+ }
162
+ }
163
+ // arrayModel/setModel/mapModel call
164
+ else if (!internal.isComposing && (0, call_js_1.calls)(path, call_js_1.modelFunctions, internal)) {
165
+ /* istanbul ignore else */
166
+ if (argPath) {
167
+ meshAllUnknown([argPath], internal);
168
+ }
169
+ path.node.arguments.unshift(t.nullLiteral());
170
+ }
171
+ // router call
172
+ else if (internal.isComposing && (0, call_js_1.calls)(path, ["router"], internal)) {
173
+ if (!internal.stateOnly) {
174
+ (0, router_1.routerReplace)(path);
175
+ }
176
+ else {
177
+ (0, lib_js_1.err)(lib_js_1.Errors.IncompatibleContext, path, "The router is not available in stores", internal);
178
+ }
179
+ }
180
+ // watch call
181
+ else if ((0, call_js_1.calls)(path, ["watch"], internal)) {
182
+ (0, lib_js_1.processCalculateCall)(path, internal);
183
+ }
184
+ else if (path.isCallExpression() &&
185
+ t.isIdentifier(path.node.callee) &&
186
+ path.node.callee.name.startsWith("prompt")) {
187
+ if (!internal.isComposing) {
188
+ (0, lib_js_1.err)(lib_js_1.Errors.IncompatibleContext, path, "Prompts can be constructed only from components", internal);
189
+ }
190
+ path.node.arguments.unshift(internal_js_1.ctx);
191
+ }
192
+ // call any other function, invalid if code calls a hint
193
+ else {
194
+ if ((0, call_js_1.calls)(path, call_js_1.hintFunctions, internal)) {
195
+ (0, lib_js_1.err)(lib_js_1.Errors.IncompatibleContext, path, `Usage of hints is restricted here`, internal);
157
196
  }
197
+ meshOrIgnoreExpression(path.get("callee"), internal);
198
+ meshAllUnknown(path.get("arguments"), internal);
158
199
  }
159
200
  break;
160
201
  }
161
202
  case "AssignmentExpression": {
162
203
  const path = nodePath;
163
- const left = path.node.left;
164
- let replaced = false;
165
- meshLValue(path.get("left"), internal);
166
- if (t.isIdentifier(left) && internal.stack.get(left.name) === 4 /* VariableState.ReactivePointer */) {
167
- const replaceWith = (0, lib_js_1.forwardOnlyExpr)(path.get("right"), path.node.right, internal);
168
- if (replaceWith) {
169
- path.get("right").replaceWith(replaceWith);
170
- replaced = true;
204
+ const left = path.get("left");
205
+ const right = path.get("right");
206
+ if (left.isMemberExpression() && !(0, expression_js_1.exprIsSure)(left, internal)) {
207
+ const property = left.node.property;
208
+ meshExpression(left.get("object"), internal);
209
+ meshExpression(right, internal);
210
+ /* istanbul ignore else */
211
+ if (!t.isPrivateName(property)) {
212
+ path.replaceWith(internal.set(left.node.object, property, right.node));
171
213
  }
172
214
  }
173
- if (!replaced) {
174
- meshExpression(path.get("right"), internal);
215
+ else {
216
+ meshLValue(left, internal);
217
+ meshExpression(right, internal);
175
218
  }
176
219
  break;
177
220
  }
@@ -184,8 +227,13 @@ function meshExpression(nodePath, internal, isRoot) {
184
227
  if (t.isExpression(property) && !t.isIdentifier(property)) {
185
228
  meshOrIgnoreExpression(path.get("property"), internal);
186
229
  }
187
- if ((0, expression_js_1.memberIsIValue)(node, internal)) {
188
- path.replaceWith(t.memberExpression(node, t.identifier("$")));
230
+ if ((0, expression_js_1.memberIsIValue)(node)) {
231
+ if ((0, expression_js_1.exprIsSure)(path, internal)) {
232
+ path.replaceWith(t.memberExpression(path.node, t.identifier("V")));
233
+ }
234
+ else {
235
+ path.replaceWith(t.optionalMemberExpression(path.node, t.identifier("V"), false, true));
236
+ }
189
237
  }
190
238
  break;
191
239
  }
@@ -260,48 +308,7 @@ function meshExpression(nodePath, internal, isRoot) {
260
308
  break;
261
309
  }
262
310
  case "ObjectExpression": {
263
- const path = nodePath;
264
- for (const propPath of path.get("properties")) {
265
- const prop = propPath.node;
266
- if (t.isObjectProperty(prop)) {
267
- const path = propPath;
268
- const valuePath = path.get("value");
269
- let replaced = false;
270
- if (isRoot &&
271
- internal.stateOnly &&
272
- !path.node.computed &&
273
- t.isIdentifier(path.node.key) &&
274
- t.isExpression(valuePath.node)) {
275
- const call = (0, lib_js_1.exprCall)(valuePath, valuePath.node, internal);
276
- if (call) {
277
- if (path.node.key.name.startsWith("$")) {
278
- valuePath.replaceWith(call);
279
- }
280
- else {
281
- throw path.buildCodeFrameError("Vasille: Reactive value property name must start with $");
282
- }
283
- replaced = true;
284
- }
285
- else if (t.isIdentifier(valuePath.node) &&
286
- internal.stack.get(valuePath.node.name) === 3 /* VariableState.ReactiveObject */ &&
287
- !path.node.key.name.startsWith("$$")) {
288
- throw path.buildCodeFrameError("Vasille: Reactive object property name must start with $$");
289
- }
290
- }
291
- if (!replaced) {
292
- meshOrIgnoreExpression(valuePath, internal);
293
- }
294
- }
295
- else if (t.isObjectMethod(prop)) {
296
- meshFunction(propPath, internal);
297
- }
298
- else if (isRoot && internal.stateOnly && t.isSpreadElement(prop)) {
299
- throw propPath.buildCodeFrameError("Vasille: Spread element is not allowed here");
300
- }
301
- else {
302
- meshAllUnknown([propPath], internal);
303
- }
304
- }
311
+ processObjectExpression(nodePath, internal);
305
312
  break;
306
313
  }
307
314
  case "FunctionExpression": {
@@ -313,14 +320,21 @@ function meshExpression(nodePath, internal, isRoot) {
313
320
  break;
314
321
  }
315
322
  case "ClassExpression": {
316
- meshClassBody(nodePath.get("body"), internal);
323
+ const classPath = nodePath;
324
+ const idPath = classPath.get("id");
325
+ if (idPath.isIdentifier()) {
326
+ (0, lib_js_1.checkNonReactiveName)(idPath, internal);
327
+ }
328
+ meshClassBody(classPath.get("body"), internal);
317
329
  break;
318
330
  }
319
331
  case "JSXFragment": {
320
- throw nodePath.buildCodeFrameError("Vasille: JSX fragment is not allowed here");
332
+ (0, lib_js_1.err)(lib_js_1.Errors.IncompatibleContext, nodePath, "JSX fragment is not allowed here", internal);
333
+ break;
321
334
  }
322
335
  case "JSXElement": {
323
- throw nodePath.buildCodeFrameError("Vasille: JSX element is not allowed here");
336
+ (0, lib_js_1.err)(lib_js_1.Errors.IncompatibleContext, nodePath, "JSX element is not allowed here", internal);
337
+ break;
324
338
  }
325
339
  }
326
340
  }
@@ -329,72 +343,136 @@ function meshStatements(paths, internal) {
329
343
  meshStatement(path, internal);
330
344
  }
331
345
  }
332
- function ignoreParams(val, internal) {
333
- if (t.isAssignmentPattern(val)) {
334
- val = val.left;
346
+ function ignoreParams(path, internal, allowReactiveId) {
347
+ /* istanbul ignore else */
348
+ // param with default value
349
+ if (path.isAssignmentPattern()) {
350
+ const left = path.get("left");
351
+ meshExpression(path.get("right"), internal);
352
+ ignoreParams(left, internal, false);
353
+ /* istanbul ignore else */
354
+ if (!allowReactiveId && left.isIdentifier()) {
355
+ (0, lib_js_1.checkNonReactiveName)(left, internal);
356
+ }
335
357
  }
336
- if (t.isIdentifier(val)) {
337
- internal.stack.set(val.name, 1 /* VariableState.Ignored */);
358
+ // param is identifier
359
+ else if (path.isIdentifier()) {
360
+ internal.stack.set(path.node.name, {});
361
+ if (!allowReactiveId || !allowReactiveId.includes("id")) {
362
+ (0, lib_js_1.checkNonReactiveName)(path, internal);
363
+ }
338
364
  }
339
- else if (t.isObjectPattern(val)) {
340
- ignoreObjectPattern(val, internal);
365
+ // param is object destruction
366
+ else if (path.isObjectPattern()) {
367
+ ignoreObjectPattern(path, internal);
341
368
  }
342
- else if (t.isArrayPattern(val)) {
343
- for (const element of val.elements) {
369
+ // param is array destruction
370
+ else if (path.isArrayPattern()) {
371
+ for (const element of path.get("elements")) {
344
372
  if (element) {
345
- ignoreParams(element, internal);
373
+ ignoreParams(element, internal, allowReactiveId && allowReactiveId.includes("array") && ["id", "array"]);
374
+ if ((!allowReactiveId || !allowReactiveId.includes("array")) && element.isIdentifier()) {
375
+ (0, lib_js_1.checkNonReactiveName)(element, internal);
376
+ }
346
377
  }
347
378
  }
348
379
  }
380
+ // rest element
381
+ else if (path.isRestElement()) {
382
+ ignoreParams(path.get("argument"), internal, false);
383
+ }
384
+ // something else
385
+ else {
386
+ meshLValue(path, internal);
387
+ }
349
388
  }
350
389
  function ignoreObjectPattern(pattern, internal) {
351
- for (const property of pattern.properties) {
352
- if (t.isObjectProperty(property)) {
353
- if (t.isObjectPattern(property.value)) {
354
- ignoreObjectPattern(property.value, internal);
390
+ for (const path of pattern.get("properties")) {
391
+ if (path.isObjectProperty()) {
392
+ const property = path.node;
393
+ const originName = (t.isStringLiteral(property.key) && property.key.value) ||
394
+ (!property.computed && t.isIdentifier(property.key) && property.key.name);
395
+ const newName = (t.isIdentifier(property.value) && property.value.name) ||
396
+ (t.isAssignmentPattern(property.value) && t.isIdentifier(property.value.left) && property.value.left.name);
397
+ if (originName && newName && originName.startsWith("$") !== newName.startsWith("$")) {
398
+ (0, lib_js_1.err)(lib_js_1.Errors.RulesOfVasille, path.get("value"), `Property "${originName}" can not be renamed to "${newName}": ` +
399
+ (originName.startsWith("$") ? `rename it to "$${newName}"` : `rename it to "${newName.substring(1)}"`), internal);
400
+ }
401
+ const valuePath = path.get("value");
402
+ /* istanbul ignore else */
403
+ if (valuePath.isObjectPattern()) {
404
+ /* istanbul ignore else */
405
+ if (originName && originName.startsWith("$")) {
406
+ (0, lib_js_1.err)(lib_js_1.Errors.RulesOfVasille, path, "You can not destruct a reactive value", internal);
407
+ }
408
+ ignoreObjectPattern(path.get("value"), internal);
355
409
  }
356
- else if (t.isAssignmentPattern(property.value)) {
357
- ignoreParams(property.value, internal);
410
+ else if (valuePath.isAssignmentPattern()) {
411
+ const right = valuePath.get("right");
412
+ ignoreParams(valuePath.get("left"), internal, ["id"]);
413
+ meshExpression(right, internal);
414
+ if (property.computed && t.isIdentifier(property.key)) {
415
+ right.replaceWith(internal.match(t.stringLiteral(property.key.name), right.node));
416
+ }
417
+ else if ((t.isIdentifier(property.key) && property.key.name.startsWith("$")) ||
418
+ (t.isStringLiteral(property.key) && property.key.value.startsWith("$"))) {
419
+ right.replaceWith(internal.ref(right.node));
420
+ }
358
421
  }
359
422
  else if (t.isIdentifier(property.value)) {
360
- internal.stack.set(property.value.name, 1 /* VariableState.Ignored */);
423
+ internal.stack.set(property.value.name, {});
424
+ if (property.computed) {
425
+ path
426
+ .get("value")
427
+ .replaceWith(t.assignmentPattern(property.value, internal.match(t.stringLiteral(property.value.name))));
428
+ }
429
+ else if (property.value.name.startsWith("$")) {
430
+ path.get("value").replaceWith(t.assignmentPattern(property.value, internal.ref()));
431
+ }
361
432
  }
362
433
  }
363
- if (t.isRestElement(property)) {
364
- internal.stack.set(property.argument.name, 1 /* VariableState.Ignored */);
434
+ if (path.isRestElement() && t.isIdentifier(path.node.argument)) {
435
+ internal.stack.set(path.node.argument.name, {});
365
436
  }
366
437
  }
367
438
  }
368
439
  function reactiveArrayPattern(path, internal) {
369
- if (t.isArrayPattern(path.node)) {
370
- path.node.elements.forEach((element, index) => {
371
- if (t.isIdentifier(element)) {
372
- internal.stack.set(element.name, index < 2 ? 2 /* VariableState.Reactive */ : 1 /* VariableState.Ignored */);
440
+ if (path.isArrayPattern()) {
441
+ path.get("elements").forEach((element, index) => {
442
+ /* istanbul ignore else */
443
+ if (index < 2) {
444
+ (0, lib_js_1.checkReactiveName)(element, internal);
445
+ }
446
+ else if (element.isIdentifier()) {
447
+ (0, lib_js_1.checkNonReactiveName)(element, internal);
448
+ internal.stack.set(element.node.name, {});
373
449
  }
374
450
  });
375
451
  }
376
452
  else {
377
- throw path.buildCodeFrameError("Vasille: Expected array pattern");
453
+ (0, lib_js_1.err)(lib_js_1.Errors.TokenNotSupported, path, "Expected array pattern", internal);
378
454
  }
379
455
  }
380
456
  function meshForEachHeader(path, internal) {
381
457
  const left = path.node.left;
382
458
  meshExpression(path.get("right"), internal);
459
+ /* istanbul ignore else */
383
460
  if (t.isVariableDeclaration(left) && t.isVariableDeclarator(left.declarations[0])) {
384
- ignoreParams(left.declarations[0].id, internal);
461
+ ignoreParams(path.get("left").get("declarations")[0].get("id"), internal, false);
385
462
  }
386
463
  }
387
464
  function meshForHeader(path, internal) {
388
465
  const node = path.node;
466
+ /* istanbul ignore else */
389
467
  if (node.init) {
390
- if (t.isExpression(node.init)) {
391
- meshExpression(path.get("init"), internal);
468
+ const initPath = path.get("init");
469
+ if (initPath.isExpression()) {
470
+ meshExpression(initPath, internal);
392
471
  }
393
472
  else {
394
- const variablePath = path.get("init");
395
- for (const declarationPath of variablePath.get("declarations")) {
473
+ for (const declarationPath of initPath.get("declarations")) {
396
474
  meshExpression(declarationPath.get("init"), internal);
397
- ignoreParams(declarationPath.node.id, internal);
475
+ ignoreParams(declarationPath.get("id"), internal, false);
398
476
  }
399
477
  }
400
478
  }
@@ -403,10 +481,92 @@ function meshForHeader(path, internal) {
403
481
  }
404
482
  function meshClassBody(path, internal) {
405
483
  for (const item of path.get("body")) {
406
- if (t.isClassMethod(item.node) || t.isClassPrivateMethod(item.node)) {
484
+ /* istanbul ignore else */
485
+ if (item.isClassMethod() || item.isClassPrivateMethod()) {
407
486
  meshFunction(item, internal);
408
487
  }
488
+ else if (item.isClassProperty()) {
489
+ meshExpression(item.get("value"), internal);
490
+ }
491
+ else if (item.isClassAccessorProperty()) {
492
+ meshExpression(item.get("value"), internal);
493
+ }
494
+ else if (item.isClassPrivateProperty()) {
495
+ meshExpression(item.get("value"), internal);
496
+ }
497
+ }
498
+ }
499
+ function procedureProcessObjectExpression(path, internal, state, prefix) {
500
+ for (const prop of path.get("properties")) {
501
+ const keyPath = prop.get("key");
502
+ const valuePath = prop.get("value");
503
+ /* istanbul ignore else */
504
+ if (prop.isObjectProperty()) {
505
+ // the property name is known in compile time
506
+ if ((!prop.node.computed || keyPath.isStringLiteral()) && valuePath.isExpression()) {
507
+ const call = (internal.isComposing && !internal.isFunctionParsing) ||
508
+ (0, call_js_1.calls)(valuePath, ["ref", "bind", "calculate"], internal)
509
+ ? (0, expression_js_1.checkNode)(valuePath, internal)
510
+ : null;
511
+ const name = (0, utils_1.stringify)(keyPath.node);
512
+ if ((call?.found.size ?? 0) > 0) {
513
+ (0, lib_js_1.err)(lib_js_1.Errors.RulesOfVasille, valuePath, "Objects can not contains bind expressions", internal);
514
+ }
515
+ else if (call?.self) {
516
+ if (!name.startsWith("$")) {
517
+ (0, lib_js_1.err)(lib_js_1.Errors.RulesOfVasille, keyPath, "Reactive field name must start with $", internal);
518
+ }
519
+ state[name] = 1;
520
+ }
521
+ else {
522
+ if (valuePath.isObjectExpression()) {
523
+ procedureProcessObjectExpression(valuePath, internal, state, `${prefix}${name}.`);
524
+ }
525
+ else {
526
+ meshExpression(valuePath, internal);
527
+ }
528
+ if (name.startsWith("$")) {
529
+ if (internal.isComposing && !internal.isFunctionParsing) {
530
+ valuePath.replaceWith(internal.ref(valuePath.node));
531
+ state[name] = 1;
532
+ }
533
+ else {
534
+ (0, lib_js_1.err)(lib_js_1.Errors.RulesOfVasille, prop.get("key"), "This property is not a reactive", internal);
535
+ }
536
+ }
537
+ }
538
+ }
539
+ // the property name is unknown in compile time
540
+ else {
541
+ meshOrIgnoreExpression(keyPath, internal);
542
+ meshLValue(valuePath, internal);
543
+ /* istanbul ignore else */
544
+ if (keyPath.isExpression() && valuePath.isExpression()) {
545
+ valuePath.replaceWith(internal.match(keyPath.node, valuePath.node));
546
+ }
547
+ }
548
+ }
549
+ else if (prop.isObjectMethod()) {
550
+ if ((keyPath.isIdentifier() && keyPath.node.name.startsWith("$") && !prop.node.computed) ||
551
+ (keyPath.isStringLiteral() && keyPath.node.value.startsWith("$"))) {
552
+ (0, lib_js_1.err)(lib_js_1.Errors.RulesOfVasille, prop.get("key"), "Method name can not start with $", internal);
553
+ }
554
+ meshStatement(prop.get("body"), internal);
555
+ }
556
+ else if (prop.isSpreadElement()) {
557
+ const argumentPath = prop.get("argument");
558
+ if (argumentPath.isObjectExpression()) {
559
+ procedureProcessObjectExpression(argumentPath, internal, state, prefix);
560
+ }
561
+ else {
562
+ meshExpression(argumentPath, internal);
563
+ }
564
+ }
409
565
  }
566
+ return state;
567
+ }
568
+ function processObjectExpression(path, internal) {
569
+ return procedureProcessObjectExpression(path, internal, {}, "");
410
570
  }
411
571
  function meshStatement(path, internal) {
412
572
  const statement = path.node;
@@ -487,6 +647,7 @@ function meshStatement(path, internal) {
487
647
  break;
488
648
  case "TryStatement":
489
649
  meshStatement(path.get("block"), internal);
650
+ /* istanbul ignore else */
490
651
  if (path.node.handler) {
491
652
  meshStatement(path.get("handler").get("body"), internal);
492
653
  }
@@ -495,13 +656,122 @@ function meshStatement(path, internal) {
495
656
  case "VariableDeclaration": {
496
657
  const _path = path;
497
658
  for (const declaration of _path.get("declarations")) {
498
- const expr = declaration.node.init;
499
- if (expr && t.isIdentifier(declaration.node.id) && (0, call_js_1.calls)(expr, ["compose", "store"], internal)) {
500
- meshComposeCall(expr, declaration.node.id, declaration.get("init"), internal);
659
+ const initPath = declaration.get("init");
660
+ const composeMethod = (0, call_js_1.calls)(initPath, call_js_1.composeFunctions, internal);
661
+ const id = declaration.node.id;
662
+ const idPath = declaration.get("id");
663
+ if (t.isIdentifier(id) && composeMethod) {
664
+ const name = id.name;
665
+ const idPath = declaration.get("id");
666
+ const isNotUpperCase = name[0].toUpperCase() !== name[0];
667
+ const isNotLowerCase = name[0].toLowerCase() !== name[0];
668
+ function report(error) {
669
+ (0, lib_js_1.err)(lib_js_1.Errors.RulesOfVasille, idPath, error, internal);
670
+ }
671
+ if ((0, call_js_1.calls)(initPath, ["compose", "component"], internal)) {
672
+ if (isNotUpperCase) {
673
+ report("The component name must start with a uppercase letter");
674
+ }
675
+ if (internal.strictFolders && !internal.filename.includes("/components/")) {
676
+ report("Components must be placed in a folder named `components`");
677
+ }
678
+ }
679
+ if ((0, call_js_1.calls)(initPath, ["view"], internal)) {
680
+ if (isNotUpperCase) {
681
+ report("The view name must start with a uppercase letter");
682
+ }
683
+ if (!name.endsWith("View")) {
684
+ report("The view name must end with `View`");
685
+ }
686
+ if (internal.strictFolders && !internal.filename.includes("/views/")) {
687
+ report("Views must be placed in a folder named `views`");
688
+ }
689
+ }
690
+ if ((0, call_js_1.calls)(initPath, ["store"], internal)) {
691
+ if (isNotLowerCase) {
692
+ report("The store name must start with a lowercase letter");
693
+ }
694
+ if (!name.endsWith("Store")) {
695
+ report("The store name must end with `Store`");
696
+ }
697
+ if (internal.strictFolders && !internal.filename.includes("/stores/")) {
698
+ report("Stores must be placed in a folder named `stores`");
699
+ }
700
+ }
701
+ if ((0, call_js_1.calls)(initPath, ["model"], internal)) {
702
+ if (isNotLowerCase) {
703
+ report("The model constructor function name must start with a lowercase letter");
704
+ }
705
+ if (!name.endsWith("Model")) {
706
+ report("The model constructor function name must end with `Model`");
707
+ }
708
+ if (internal.strictFolders && !internal.filename.includes("/models/")) {
709
+ report("Models must be placed in a folder named `models`");
710
+ }
711
+ }
712
+ if ((0, call_js_1.calls)(initPath, ["modal"], internal)) {
713
+ if (isNotUpperCase) {
714
+ report("The modal component name must start with a uppercase letter");
715
+ }
716
+ if (!name.endsWith("Modal")) {
717
+ report("The modal component name must end with `Modal`");
718
+ }
719
+ if (internal.strictFolders && !internal.filename.includes("/modals/")) {
720
+ report("Modals must be placed in a folder named `modals`");
721
+ }
722
+ }
723
+ if ((0, call_js_1.calls)(initPath, ["prompt"], internal)) {
724
+ if (!name.startsWith("prompt")) {
725
+ report("The prompt function name must start with `prompt`");
726
+ }
727
+ if (internal.strictFolders && !internal.filename.includes("/prompts/")) {
728
+ report("Prompts must be placed in a folder named `prompts`");
729
+ }
730
+ }
731
+ if ((0, call_js_1.calls)(initPath, ["screen"], internal)) {
732
+ if (!name.endsWith("Screen")) {
733
+ report("The screen name must start with `Screen`");
734
+ }
735
+ if (internal.strictFolders && !internal.filename.includes("/screens/")) {
736
+ report("Screens must be placed in a folder named `screens`");
737
+ }
738
+ }
739
+ if ((0, call_js_1.calls)(initPath, ["page"], internal)) {
740
+ report("Use export default instead");
741
+ }
742
+ if (t.isExportNamedDeclaration(path.parent)) {
743
+ /* istanbul ignore else */
744
+ if (![".ts", ".tsx", ".js", ".jsx"].some(ext => {
745
+ return internal.filename.endsWith(`${name}${ext}`);
746
+ })) {
747
+ report(`File name is not correct, expected ${name}.ts, ${name}.tsx, ${name}.js or ${name}.jsx`);
748
+ }
749
+ }
750
+ meshComposeCall(id.name, initPath, internal);
501
751
  }
752
+ // calculate call
753
+ else if ((0, call_js_1.calls)(initPath, ["calculate"], internal) && (0, lib_js_1.processCalculateCall)(initPath, internal)) {
754
+ (0, lib_js_1.checkReactiveName)(idPath, internal);
755
+ }
756
+ // ref call
757
+ else if ((0, call_js_1.calls)(initPath, call_js_1.reactivityFunctions, internal)) {
758
+ meshAllUnknown(initPath.get("arguments"), internal);
759
+ (0, lib_js_1.checkReactiveName)(idPath, internal);
760
+ }
761
+ // bind call
762
+ else if ((0, call_js_1.calls)(initPath, ["bind"], internal) && (0, lib_js_1.exprCall)(initPath, initPath.node, internal, { strong: true })) {
763
+ (0, lib_js_1.checkReactiveName)(idPath, internal);
764
+ }
765
+ // variable declaration
502
766
  else {
503
- meshExpression(declaration.get("init"), internal);
504
- ignoreParams(declaration.node.id, internal);
767
+ ignoreParams(declaration.get("id"), internal, ["id", "array"]);
768
+ idPath.isIdentifier() && (0, lib_js_1.checkNonReactiveName)(idPath, internal);
769
+ if (initPath.isObjectExpression() && t.isIdentifier(declaration.node.id) && _path.node.kind === "const") {
770
+ internal.stack.set(declaration.node.id.name, processObjectExpression(initPath, internal));
771
+ }
772
+ else {
773
+ meshExpression(initPath, internal);
774
+ }
505
775
  }
506
776
  }
507
777
  break;
@@ -518,116 +788,134 @@ function meshStatement(path, internal) {
518
788
  meshStatement(path.get("declaration"), internal);
519
789
  break;
520
790
  }
521
- case "ClassDeclaration":
522
- meshClassBody(path.get("body"), internal);
791
+ case "ClassDeclaration": {
792
+ const classPath = path;
793
+ const idPath = classPath.get("id");
794
+ /* istanbul ignore else */
795
+ if (idPath.isIdentifier()) {
796
+ (0, lib_js_1.checkNonReactiveName)(idPath, internal);
797
+ }
798
+ meshClassBody(classPath.get("body"), internal);
523
799
  break;
800
+ }
524
801
  case "ExportDefaultDeclaration": {
525
802
  const declarationPath = path.get("declaration");
526
- if (t.isExpression(declarationPath.node)) {
803
+ /* istanbul ignore else */
804
+ // export default 23;
805
+ if (declarationPath.isExpression()) {
527
806
  meshExpression(declarationPath, internal);
528
807
  }
529
- else if (t.isFunctionDeclaration(declarationPath.node)) {
808
+ // export default function ..
809
+ else if (declarationPath.isFunctionDeclaration()) {
530
810
  meshFunction(declarationPath, internal);
531
811
  }
532
- else if (t.isClassDeclaration(declarationPath.node)) {
812
+ // export default class ..
813
+ else if (declarationPath.isClassDeclaration()) {
533
814
  meshClassBody(declarationPath.get("body"), internal);
534
815
  }
535
816
  }
536
817
  }
537
818
  }
538
819
  function meshFunction(path, internal) {
539
- if (t.isFunctionDeclaration(path.node) && path.node.id) {
540
- internal.stack.set(path.node.id.name, 1 /* VariableState.Ignored */);
820
+ if (path.isFunctionDeclaration() && path.node.id) {
821
+ const idPath = path.get("id");
822
+ /* istanbul ignore else */
823
+ if (idPath.isIdentifier()) {
824
+ internal.stack.set(path.node.id.name, {});
825
+ (0, lib_js_1.checkNonReactiveName)(idPath, internal);
826
+ }
541
827
  }
542
828
  internal.stack.push();
543
- const node = path.node;
544
- if (t.isFunctionExpression(node) && node.id) {
545
- internal.stack.set(node.id.name, 1 /* VariableState.Ignored */);
829
+ if (path.isFunctionExpression() && path.node.id) {
830
+ internal.stack.set(path.node.id.name, {});
546
831
  }
547
- for (const param of node.params) {
548
- ignoreParams(param, internal);
832
+ for (const param of path.get("params")) {
833
+ ignoreParams(param, internal, false);
549
834
  }
550
- if (t.isExpression(node.body)) {
551
- meshExpression(path.get("body"), internal);
835
+ const bodyPath = path.get("body");
836
+ /* istanbul ignore else */
837
+ if (bodyPath.isExpression()) {
838
+ meshExpression(bodyPath, internal);
552
839
  }
553
- else {
554
- const bodyPath = path.get("body");
840
+ else if (bodyPath.isBlockStatement()) {
555
841
  meshStatement(bodyPath, internal);
556
842
  }
557
843
  internal.stack.pop();
558
844
  }
559
- function composeExpression(path, internal, isRoot) {
845
+ function composeExpression(path, internal) {
560
846
  const expr = path.node;
561
847
  switch (expr && expr.type) {
562
- case "AssignmentExpression": {
563
- meshExpression(path, internal);
564
- break;
565
- }
566
848
  case "CallExpression":
567
849
  case "OptionalCallExpression": {
568
- const call = expr;
569
- if ((0, call_js_1.calls)(call, ["watch"], internal)) {
570
- const args = (0, lib_js_1.parseCalculateCall)(path, internal);
850
+ if ((0, call_js_1.calls)(path, ["watch"], internal)) {
851
+ (0, lib_js_1.parseCalculateCall)(path, internal);
852
+ const args = path.node.arguments;
853
+ /* istanbul ignore else */
571
854
  if (args) {
572
- if (args[1].elements.length > 0) {
573
- path.replaceWith(t.callExpression(t.memberExpression(internal_js_1.ctx, t.identifier("watch")), args));
855
+ if (args[2].elements.length <= 0) {
856
+ path.replaceWith(t.callExpression(args[1], []));
574
857
  }
575
- else {
576
- path.replaceWith(t.callExpression(args[0], []));
858
+ }
859
+ }
860
+ else if ((0, call_js_1.calls)(path, ["beforeMount", "afterMount"], internal)) {
861
+ const arg = path.get("arguments")[0];
862
+ if (arg && (arg.isFunctionExpression() || arg.isArrowFunctionExpression())) {
863
+ const body = arg.isFunctionExpression() ? arg.get("body") : arg.get("body");
864
+ /* istanbul ignore else */
865
+ if (body.isBlockStatement()) {
866
+ composeStatements(body.get("body"), internal);
867
+ path.replaceWith(t.callExpression(arg.node, []));
577
868
  }
869
+ else if (body.isExpression()) {
870
+ composeExpression(body, internal);
871
+ path.replaceWith(body);
872
+ }
873
+ }
874
+ else {
875
+ (0, lib_js_1.err)(lib_js_1.Errors.IncorrectArguments, path, "Incorrect hint argument", internal);
876
+ }
877
+ }
878
+ else if ((0, call_js_1.calls)(path, ["beforeDestroy"], internal)) {
879
+ if (internal.stateOnly) {
880
+ (0, lib_js_1.err)(lib_js_1.Errors.IncompatibleContext, path, "Stores in Vasille.JS are not destroyable", internal);
578
881
  }
882
+ path.get("callee").replaceWith(t.memberExpression(internal_js_1.ctx, t.identifier("runOnDestroy")));
579
883
  }
580
884
  else {
581
885
  meshExpression(path, internal);
582
886
  }
583
887
  break;
584
888
  }
585
- case "LogicalExpression":
586
- composeExpression(path.get("left"), internal);
587
- composeExpression(path.get("right"), internal);
588
- break;
589
- case "ConditionalExpression":
590
- meshExpression(path.get("test"), internal);
591
- composeExpression(path.get("consequent"), internal);
592
- composeExpression(path.get("alternate"), internal);
593
- break;
594
889
  case "JSXElement":
595
890
  case "JSXFragment":
596
891
  if (internal.stateOnly) {
597
- throw path.buildCodeFrameError("Vasille: JSX is not allowed in states");
892
+ return (0, lib_js_1.err)(lib_js_1.Errors.IncompatibleContext, path, "JSX is not allowed in states", internal);
598
893
  }
599
- path.replaceWithMultiple((0, jsx_js_1.transformJsx)(path, internal));
894
+ const conditions = { cases: null };
895
+ path.replaceWithMultiple([
896
+ ...(0, jsx_js_1.transformJsx)(path, conditions, internal),
897
+ ...(0, jsx_js_1.processConditions)(conditions, internal),
898
+ ]);
600
899
  break;
601
900
  default:
602
- meshExpression(path, internal, isRoot);
901
+ meshExpression(path, internal);
603
902
  }
604
903
  }
605
- function composeStatements(paths, internal, isRoot) {
904
+ function composeStatements(paths, internal) {
606
905
  for (const path of paths) {
607
- composeStatement(path, internal, isRoot);
906
+ composeStatement(path, internal);
608
907
  }
609
908
  }
610
- function composeStatement(path, internal, isRoot) {
909
+ function composeStatement(path, internal) {
611
910
  const statement = path.node;
612
- if (!statement) {
613
- return;
614
- }
615
- switch (statement.type) {
911
+ switch (statement?.type) {
616
912
  case "FunctionDeclaration": {
617
913
  meshFunction(path, internal);
618
914
  break;
619
915
  }
620
916
  case "BlockStatement": {
621
917
  internal.stack.push();
622
- composeStatements(path.get("body"), internal, isRoot);
623
- internal.stack.pop();
624
- break;
625
- }
626
- case "DoWhileStatement": {
627
- const _path = path;
628
- meshExpression(_path.get("test"), internal);
629
- internal.stack.push();
630
- composeStatement(_path.get("body"), internal);
918
+ composeStatements(path.get("body"), internal);
631
919
  internal.stack.pop();
632
920
  break;
633
921
  }
@@ -635,68 +923,19 @@ function composeStatement(path, internal, isRoot) {
635
923
  composeExpression(path.get("expression"), internal);
636
924
  break;
637
925
  }
638
- case "ForInStatement": {
639
- const _path = path;
640
- internal.stack.push();
641
- meshForEachHeader(_path, internal);
642
- composeStatement(_path.get("body"), internal);
643
- internal.stack.pop();
644
- break;
645
- }
646
- case "ForStatement": {
647
- const _path = path;
648
- internal.stack.push();
649
- meshForHeader(_path, internal);
650
- composeStatement(_path.get("body"), internal);
651
- internal.stack.pop();
652
- break;
653
- }
654
- case "IfStatement": {
655
- const _path = path;
656
- meshExpression(_path.get("test"), internal);
657
- internal.stack.push();
658
- composeStatement(_path.get("consequent"), internal);
659
- internal.stack.pop();
660
- internal.stack.push();
661
- composeStatement(_path.get("alternate"), internal);
662
- internal.stack.pop();
663
- break;
664
- }
665
- case "LabeledStatement":
666
- composeStatement(path.get("body"), internal);
667
- break;
668
926
  case "ReturnStatement":
669
- composeExpression(path.get("argument"), internal, isRoot);
670
- break;
671
- case "SwitchStatement": {
672
- const _path = path;
673
- meshExpression(_path.get("discriminant"), internal);
674
- internal.stack.push();
675
- for (const _case of _path.get("cases")) {
676
- meshExpression(_case.get("test"), internal);
677
- composeStatements(_case.get("consequent"), internal);
678
- }
679
- internal.stack.pop();
680
- break;
681
- }
682
- case "TryStatement":
683
- const tryHandler = path.get("handler");
684
- composeStatement(path.get("block"), internal);
685
- tryHandler.node && composeStatement(tryHandler.get("body"), internal);
686
- composeStatement(path.get("finalizer"), internal);
927
+ composeExpression(path.get("argument"), internal);
687
928
  break;
688
929
  case "VariableDeclaration": {
689
930
  const _path = path;
690
931
  const kind = _path.node.kind;
691
- const declares = kind === "const" ? 1 /* VariableState.Ignored */ : 2 /* VariableState.Reactive */;
692
- if (kind === "let" || kind === "var") {
693
- _path.node.kind = "const";
694
- }
932
+ let switchToConst = true;
695
933
  for (const declaration of _path.get("declarations")) {
696
934
  const id = declaration.node.id;
697
935
  let meshInit = true;
698
936
  function idName(target = id) {
699
937
  let name = "#";
938
+ /* istanbul ignore else */
700
939
  if (t.isIdentifier(target)) {
701
940
  name = target.name;
702
941
  }
@@ -704,216 +943,157 @@ function composeStatement(path, internal, isRoot) {
704
943
  }
705
944
  function idDoubleName() {
706
945
  const pattern = id;
707
- return [idName(pattern.elements[0]), idName(pattern.elements[1])];
946
+ return [idName(pattern.elements?.[0]), idName(pattern.elements?.[1])];
708
947
  }
709
- ignoreParams(declaration.node.id, internal);
710
- if ((0, call_js_1.calls)(declaration.node.init, ["awaited"], internal)) {
948
+ ignoreParams(declaration.get("id"), internal, ["id", "array"]);
949
+ /* istanbul ignore else */
950
+ if ((0, call_js_1.calls)(declaration.get("init"), ["awaited"], internal)) {
951
+ const callPath = declaration.get("init");
711
952
  reactiveArrayPattern(declaration.get("id"), internal);
712
- meshAllUnknown(declaration.get("init").get("arguments"), internal);
713
- (0, lib_js_1.named)(declaration.node.init, idDoubleName(), internal);
953
+ meshAllUnknown(callPath.get("arguments"), internal);
954
+ /* istanbul ignore else */
955
+ if (internal.devMode) {
956
+ callPath.node.arguments.push(internal_js_1.ctx);
957
+ }
958
+ (0, lib_js_1.named)(callPath.node, idDoubleName(), internal, 2);
714
959
  meshInit = false;
715
960
  }
716
961
  else if (t.isIdentifier(id)) {
717
- internal.stack.set(id.name, declares);
962
+ const idPath = declaration.get("id");
963
+ internal.stack.set(id.name, {});
718
964
  const init = declaration.node.init;
719
- if ((0, call_js_1.calls)(init, ["value"], internal)) {
720
- internal.stack.set(id.name, 1 /* VariableState.Ignored */);
965
+ const initPath = declaration.get("init");
966
+ // let a = raw(0)
967
+ if ((0, call_js_1.calls)(initPath, ["raw"], internal)) {
721
968
  declaration.get("init").replaceWith(init.arguments[0]);
722
969
  _path.node.kind = kind;
970
+ switchToConst = false;
971
+ (0, lib_js_1.checkNonReactiveName)(idPath, internal);
723
972
  }
724
- else if ((0, call_js_1.calls)(init, ["bind"], internal)) {
973
+ // const x = bind(a + b);
974
+ else if ((0, call_js_1.calls)(initPath, ["bind", "calculate"], internal)) {
725
975
  const argument = init.arguments[0];
726
- const argumentPath = declaration.get("init").get("arguments")[0];
727
- let replaceWith = declares === 2 /* VariableState.Reactive */
728
- ? (0, lib_js_1.forwardOnlyExpr)(argumentPath, argument, internal)
729
- : (0, lib_js_1.exprCall)(argumentPath, argument, internal, idName());
730
- if (!replaceWith) {
731
- replaceWith =
732
- declares === 2 /* VariableState.Reactive */
733
- ? t.callExpression(t.memberExpression(internal.id, t.identifier("r")), [argument])
734
- : (0, lib_js_1.ref)(argument, internal, idName());
976
+ const isReactive = (0, lib_js_1.exprCall)(initPath, initPath.node, internal, { name: idName(), strong: true });
977
+ meshInit = !isReactive;
978
+ if (!isReactive) {
979
+ declaration.get("init").replaceWith((0, lib_js_1.ref)(argument, internal, idName()));
735
980
  }
736
- if (declares === 2 /* VariableState.Reactive */) {
737
- internal.stack.set(id.name, 4 /* VariableState.ReactivePointer */);
738
- replaceWith = (0, lib_js_1.own)(replaceWith, internal, idName());
739
- }
740
- else {
741
- internal.stack.set(id.name, 2 /* VariableState.Reactive */);
742
- }
743
- declaration.get("init").replaceWith(replaceWith);
744
- meshInit = !replaceWith;
981
+ (0, lib_js_1.checkReactiveName)(idPath, internal);
745
982
  }
746
- else if ((0, call_js_1.calls)(init, ["ref"], internal)) {
983
+ // let y = ref(2)
984
+ else if ((0, call_js_1.calls)(initPath, ["ref"], internal)) {
985
+ meshAllUnknown(initPath.get("arguments"), internal);
747
986
  const argument = init.arguments[0];
748
- internal.stack.set(id.name, 2 /* VariableState.Reactive */);
749
987
  declaration.get("init").replaceWith((0, lib_js_1.ref)(t.isExpression(argument) ? argument : null, internal, idName()));
988
+ (0, lib_js_1.checkReactiveName)(idPath, internal);
989
+ meshInit = false;
750
990
  }
751
- else if ((0, call_js_1.calls)(init, ["reactiveObject"], internal)) {
752
- const value = init.arguments[0];
753
- if (kind !== "const") {
754
- throw declaration.buildCodeFrameError(`Vasille: Reactive objects must be must be declared as constants`);
755
- }
756
- if (t.isObjectExpression(value)) {
757
- declaration.get("init").replaceWith((0, lib_js_1.reactiveObject)(value, internal, idName()));
758
- internal.stack.set(id.name, 3 /* VariableState.ReactiveObject */);
759
- }
760
- else {
761
- throw declaration.buildCodeFrameError(`Vasille: reactiveObject requires object expression as argument`);
762
- }
991
+ // const arr = arrayModel()
992
+ else if ((0, call_js_1.calls)(initPath, ["arrayModel"], internal)) {
993
+ (0, lib_js_1.processModelCall)(initPath, "Array", kind === "const", internal, idName());
994
+ meshInit = false;
995
+ (0, lib_js_1.checkNonReactiveName)(idPath, internal);
763
996
  }
764
- else if ((0, call_js_1.calls)(init, ["arrayModel"], internal)) {
765
- const value = init.arguments[0];
766
- if (kind !== "const") {
767
- throw declaration.buildCodeFrameError(`Vasille: Array models must be must be declared as constants`);
768
- }
769
- if (t.isArrayExpression(value)) {
770
- declaration.get("init").replaceWith((0, lib_js_1.arrayModel)(value, internal, idName()));
771
- }
772
- else {
773
- declaration.get("init").replaceWith((0, lib_js_1.arrayModel)(null, internal, idName()));
774
- }
997
+ // const map = mapModel();
998
+ else if ((0, call_js_1.calls)(initPath, ["mapModel"], internal)) {
999
+ (0, lib_js_1.processModelCall)(initPath, "Map", kind === "const", internal, idName());
1000
+ meshInit = false;
1001
+ (0, lib_js_1.checkNonReactiveName)(idPath, internal);
775
1002
  }
776
- else if ((0, call_js_1.calls)(init, ["mapModel", "setModel"], internal)) {
777
- const args = init.arguments;
778
- const name = (0, call_js_1.calls)(init, ["mapModel", "setModel"], internal);
779
- if (kind !== "const") {
780
- throw declaration.buildCodeFrameError(`Vasille: ${name === "mapModel" ? "Map" : "Set"} models must be declared as constants`);
781
- }
782
- declaration
783
- .get("init")
784
- .replaceWith(name === "mapModel" ? (0, lib_js_1.mapModel)(args, internal, idName()) : (0, lib_js_1.setModel)(args, internal, idName()));
1003
+ // const set = setModel();
1004
+ else if ((0, call_js_1.calls)(initPath, ["setModel"], internal)) {
1005
+ (0, lib_js_1.processModelCall)(initPath, "Set", kind === "const", internal, idName());
1006
+ meshInit = false;
1007
+ (0, lib_js_1.checkNonReactiveName)(idPath, internal);
785
1008
  }
1009
+ // const x = { .. }
786
1010
  else if (t.isObjectExpression(init)) {
787
- if (kind !== "const") {
788
- throw declaration.buildCodeFrameError(`Vasille: Objects must be must be declared as constants`);
789
- }
790
- declaration.get("init").replaceWith((0, lib_js_1.reactiveObject)(init, internal, idName()));
791
- internal.stack.set(id.name, 3 /* VariableState.ReactiveObject */);
1011
+ internal.stack.set(id.name, processObjectExpression(initPath, internal));
1012
+ meshInit = false;
1013
+ (0, lib_js_1.checkNonReactiveName)(idPath, internal);
792
1014
  }
793
- else if (t.isArrayExpression(init)) {
1015
+ // const a = []
1016
+ else if (initPath.isArrayExpression()) {
794
1017
  if (kind !== "const") {
795
- throw declaration.buildCodeFrameError(`Vasille: Arrays must be must be declared as constants`);
1018
+ (0, lib_js_1.err)(lib_js_1.Errors.RulesOfVasille, declaration, "Arrays must be must be declared as constants", internal);
796
1019
  }
797
- declaration.get("init").replaceWith((0, lib_js_1.arrayModel)(init, internal, idName()));
798
- }
799
- else if (t.isNewExpression(init) && t.isIdentifier(init.callee)) {
800
- if (init.callee.name === "Map" || init.callee.name === "Set") {
801
- if (kind !== "const") {
802
- throw declaration.buildCodeFrameError(`Vasille: ${init.callee.name === "Map" ? "Maps" : "Sets"} must be declared as constants`);
803
- }
804
- declaration
805
- .get("init")
806
- .replaceWith(init.callee.name === "Map"
807
- ? (0, lib_js_1.mapModel)(init.arguments, internal, idName())
808
- : (0, lib_js_1.setModel)(init.arguments, internal, idName()));
1020
+ meshExpression(initPath, internal);
1021
+ meshInit = false;
1022
+ initPath.replaceWith((0, lib_js_1.arrayModel)([initPath.node], internal, idName()));
1023
+ (0, lib_js_1.checkNonReactiveName)(idPath, internal);
1024
+ }
1025
+ // const s = new Set(), const m = new Map()
1026
+ else if (initPath.isNewExpression() && t.isIdentifier(initPath.node.callee)) {
1027
+ const name = initPath.node.callee.name;
1028
+ if (name === "Map" || name === "Set") {
1029
+ (0, lib_js_1.processModelCall)(initPath, name, kind === "const", internal, idName());
1030
+ meshInit = false;
1031
+ (0, lib_js_1.checkNonReactiveName)(idPath, internal);
809
1032
  }
810
1033
  }
811
- else if (declares === 2 /* VariableState.Reactive */) {
812
- const replaceWith = (0, lib_js_1.forwardOnlyExpr)(declaration.get("init"), declaration.node.init, internal);
813
- meshInit = !replaceWith;
814
- internal.stack.set(id.name, replaceWith ? 4 /* VariableState.ReactivePointer */ : 2 /* VariableState.Reactive */);
815
- declaration
816
- .get("init")
817
- .replaceWith(replaceWith ? (0, lib_js_1.own)(replaceWith, internal, idName()) : (0, lib_js_1.ref)(declaration.node.init, internal, idName()));
1034
+ else if (kind === "let") {
1035
+ meshExpression(declaration.get("init"), internal);
1036
+ declaration.get("init").replaceWith((0, lib_js_1.ref)(declaration.node.init, internal, idName()));
1037
+ (0, lib_js_1.checkReactiveName)(idPath, internal);
1038
+ meshInit = false;
818
1039
  }
819
1040
  else {
820
- const replaceWith = (0, lib_js_1.exprCall)(declaration.get("init"), declaration.node.init, internal, idName());
821
- if (replaceWith) {
822
- declaration.get("init").replaceWith(replaceWith);
1041
+ const isReactive = (0, lib_js_1.exprCall)(declaration.get("init"), declaration.node.init, internal, {
1042
+ name: idName(),
1043
+ strong: true,
1044
+ });
1045
+ if (isReactive) {
1046
+ (0, lib_js_1.checkReactiveName)(idPath, internal);
823
1047
  }
824
- internal.stack.set(id.name, replaceWith
825
- ? 2 /* VariableState.Reactive */
826
- : (0, expression_js_1.nodeIsReactiveObject)(declaration.get("init"), internal)
827
- ? 3 /* VariableState.ReactiveObject */
828
- : 1 /* VariableState.Ignored */);
829
- meshInit = !replaceWith;
1048
+ else {
1049
+ (0, lib_js_1.checkNonReactiveName)(idPath, internal);
1050
+ }
1051
+ meshInit = !isReactive;
830
1052
  }
831
1053
  }
1054
+ else if (t.isObjectPattern(id)) {
1055
+ ignoreObjectPattern(declaration.get("id"), internal);
1056
+ }
832
1057
  if (meshInit) {
833
1058
  meshExpression(declaration.get("init"), internal);
834
1059
  }
835
1060
  }
836
- break;
837
- }
838
- case "WhileStatement": {
839
- const _path = path;
840
- meshExpression(_path.get("test"), internal);
841
- internal.stack.push();
842
- composeStatement(_path.get("body"), internal);
843
- internal.stack.pop();
844
- break;
845
- }
846
- case "ForOfStatement": {
847
- const _path = path;
848
- internal.stack.push();
849
- meshForEachHeader(_path, internal);
850
- composeStatement(_path.get("body"), internal);
851
- internal.stack.pop();
1061
+ if (switchToConst && kind === "let") {
1062
+ _path.node.kind = "const";
1063
+ }
852
1064
  break;
853
1065
  }
854
1066
  default:
855
1067
  meshStatement(path, internal);
856
1068
  }
857
1069
  }
858
- function compose(path, internal, isInternalSlot) {
1070
+ function compose(path, internal, isInternalSlot, isSlot) {
859
1071
  internal.stack.push();
860
1072
  const node = path.node;
861
1073
  const params = node.params;
862
- const body = node.body;
1074
+ const body = path.isArrowFunctionExpression() ? path.get("body") : path.get("body");
863
1075
  if (t.isFunctionExpression(node) && node.id) {
864
- internal.stack.set(node.id.name, 1 /* VariableState.Ignored */);
1076
+ internal.stack.set(node.id.name, {});
865
1077
  }
866
1078
  if (params.length > 1 && !isInternalSlot) {
867
- throw path.get("params")[1].buildCodeFrameError("Vasille: JSX component must have no more then 1 parameter");
1079
+ (0, lib_js_1.err)(lib_js_1.Errors.IncorrectArguments, path.get("params")[1], "Extra parameters are not allowed", internal);
868
1080
  }
869
1081
  for (const param of path.get("params")) {
870
- const node = param.node;
871
- if (t.isAssignmentPattern(node)) {
872
- throw param.buildCodeFrameError("Vasille: No default value allowed here");
873
- }
874
- if (t.isIdentifier(node)) {
875
- internal.stack.set(node.name, isInternalSlot ? 1 /* VariableState.Ignored */ : 3 /* VariableState.ReactiveObject */);
876
- }
877
- else if (isInternalSlot && t.isObjectPattern(node)) {
878
- ignoreObjectPattern(node, internal);
879
- }
880
- else if (t.isObjectPattern(node)) {
881
- for (const prop of param.get("properties")) {
882
- const node = prop.node;
883
- if (t.isObjectProperty(node)) {
884
- const key = node.key;
885
- let keyName = "";
886
- if (t.isIdentifier(node.value)) {
887
- keyName = node.value.name;
888
- }
889
- else if (t.isIdentifier(key) && !node.computed) {
890
- keyName = key.name;
891
- }
892
- internal.stack.set(keyName, 2 /* VariableState.Reactive */);
893
- if (t.isAssignmentPattern(node.value)) {
894
- const assignPath = prop.get("value");
895
- assignPath
896
- .get("right")
897
- .replaceWith(t.callExpression(t.memberExpression(internal.id, t.identifier("r")), [assignPath.node.right]));
898
- }
899
- else if (!t.isIdentifier(node.value)) {
900
- throw prop.buildCodeFrameError("Vasille: Value decomposition is not allowed here");
901
- }
902
- }
903
- if (t.isRestElement(node)) {
904
- internal.stack.set(node.argument.name, 3 /* VariableState.ReactiveObject */);
905
- }
906
- }
907
- }
908
- else {
909
- throw param.buildCodeFrameError("Vasille: Expected identifier or object pattern");
910
- }
1082
+ ignoreParams(param, internal, false);
1083
+ }
1084
+ if (!isSlot) {
1085
+ internal.isComposing = true;
1086
+ }
1087
+ /* istanbul ignore else */
1088
+ if (body.isExpression()) {
1089
+ composeExpression(body, internal);
911
1090
  }
912
- if (t.isExpression(body)) {
913
- composeExpression(path.get("body"), internal, true);
1091
+ else if (body.isBlockStatement()) {
1092
+ (0, order_check_1.checkOrder)(body.get("body"), internal);
1093
+ composeStatement(body, internal);
914
1094
  }
915
- else if (t.isBlockStatement(body)) {
916
- composeStatement(path.get("body"), internal, true);
1095
+ if (!isSlot) {
1096
+ internal.isComposing = false;
917
1097
  }
918
1098
  internal.stack.pop();
919
1099
  }