voodoojs 0.7.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +1 -1
  2. package/dist/{chunk-4T2UIPWX.js → chunk-246ZC2JD.js} +4 -4
  3. package/dist/{chunk-YOZTHZS2.js → chunk-2UST7MKN.js} +3 -3
  4. package/dist/{chunk-II3XBOAP.js → chunk-4MJIS5RZ.js} +13 -13
  5. package/dist/{chunk-QO3I7VLJ.js → chunk-5D7TM3GL.js} +5 -5
  6. package/dist/{chunk-JB2YYNK6.js → chunk-5E3UZREN.js} +325 -64
  7. package/dist/{chunk-MMLUK37L.js → chunk-D4DNTWIS.js} +4 -3
  8. package/dist/{chunk-WSDB7K4X.js → chunk-DNIQLT66.js} +6 -6
  9. package/dist/{chunk-ZIWLQZZL.js → chunk-F3Z3HMZR.js} +4 -4
  10. package/dist/{chunk-GIWKGFGY.js → chunk-KQRWQPD6.js} +4 -4
  11. package/dist/{chunk-CYN6VLMD.js → chunk-RREZZ4FB.js} +4 -4
  12. package/dist/{chunk-E5T65CEI.js → chunk-WYSN4IOV.js} +5 -5
  13. package/dist/essential.cjs +317 -58
  14. package/dist/essential.d.cts +2 -2
  15. package/dist/essential.d.ts +2 -2
  16. package/dist/essential.js +10 -10
  17. package/dist/gpu.cjs +1 -1
  18. package/dist/gpu.js +10 -10
  19. package/dist/http.cjs +1 -1
  20. package/dist/http.js +5 -5
  21. package/dist/index.cjs +596 -76
  22. package/dist/index.d.cts +118 -4
  23. package/dist/index.d.ts +118 -4
  24. package/dist/index.js +282 -31
  25. package/dist/{query-CC-_z7v0.d.ts → query-Cf-7iibE.d.ts} +53 -2
  26. package/dist/{query-sEJXe_cO.d.cts → query-DiQAS73Q.d.cts} +53 -2
  27. package/dist/reactivity.cjs +1 -1
  28. package/dist/reactivity.js +2 -2
  29. package/dist/socket.cjs +303 -57
  30. package/dist/socket.js +9 -9
  31. package/dist/style-BSEVBI4K.js +5 -0
  32. package/dist/utils.cjs +1 -1
  33. package/dist/utils.js +2 -2
  34. package/dist/voodoo.core.js +322 -58
  35. package/dist/voodoo.core.min.js +18 -18
  36. package/dist/voodoo.full.js +599 -74
  37. package/dist/voodoo.full.min.js +61 -61
  38. package/dist/voodoo.js +322 -58
  39. package/dist/voodoo.min.js +25 -25
  40. package/package.json +127 -127
  41. package/dist/style-SLQ6PHZK.js +0 -5
package/README.md CHANGED
@@ -22,7 +22,7 @@ npm install voodoojs
22
22
  Or drop it into a page, with nothing else:
23
23
 
24
24
  ```html
25
- <script src="https://cdn.jsdelivr.net/npm/voodoojs@0.6/dist/voodoo.min.js" defer></script>
25
+ <script src="https://cdn.jsdelivr.net/npm/voodoojs@0.10/dist/voodoo.min.js" defer></script>
26
26
 
27
27
  <div v-data="{ count: 0 }">
28
28
  <button @click="count++">Clicked { count } times</button>
@@ -1,7 +1,7 @@
1
- import { __publicField } from './chunk-YOZTHZS2.js';
1
+ import { __publicField } from './chunk-2UST7MKN.js';
2
2
 
3
3
  /**
4
- * Voodoo.js v0.7.0
4
+ * Voodoo.js v0.10.1
5
5
  * JavaScript feels like magic.
6
6
  * (c) 2026 Voodoo.js contributors. MIT License.
7
7
  */
@@ -637,5 +637,5 @@ function traverse(value, seen = /* @__PURE__ */ new Set()) {
637
637
  }
638
638
 
639
639
  export { EffectScope, ITERATE_KEY, ReactiveEffect, TriggerType, computed, effect, effectScope, enableTracking, flushSync, getActiveEffect, getActiveScope, handleError, hasChanged, isReactive, isRef, markRaw, nextTick, pauseTracking, queueJob, queuePostFlush, reactive, ref, resetTracking, setErrorHandler, shallowRef, stop, toRaw, track, trigger, unref, warn, watch, watchEffect };
640
- //# sourceMappingURL=chunk-4T2UIPWX.js.map
641
- //# sourceMappingURL=chunk-4T2UIPWX.js.map
640
+ //# sourceMappingURL=chunk-246ZC2JD.js.map
641
+ //# sourceMappingURL=chunk-246ZC2JD.js.map
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Voodoo.js v0.7.0
2
+ * Voodoo.js v0.10.1
3
3
  * JavaScript feels like magic.
4
4
  * (c) 2026 Voodoo.js contributors. MIT License.
5
5
  */
@@ -12,5 +12,5 @@ var __export = (target, all) => {
12
12
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
13
13
 
14
14
  export { __export, __publicField };
15
- //# sourceMappingURL=chunk-YOZTHZS2.js.map
16
- //# sourceMappingURL=chunk-YOZTHZS2.js.map
15
+ //# sourceMappingURL=chunk-2UST7MKN.js.map
16
+ //# sourceMappingURL=chunk-2UST7MKN.js.map
@@ -1,14 +1,14 @@
1
- import { http, HttpError, request } from './chunk-WSDB7K4X.js';
2
- import { stringify, markInitialized, markSkipChildren, destroy, walk, removeQuietly, evaluateIn, addCleanup, markNodeScope, setComponentMounter, closestDirective, magic, readAttr, hasAttr, componentAliases, Scope, queryDirective, parse, evaluate, parseAttribute, originalAttributes, hasDirective, findScope, VoodooRuntimeError, VoodooSyntaxError, allowedGlobals, clearParseCache, tokenize, getScope, stopObserving, refresh, start, magics, rootScope, isInitialized, restoreAttributes, hasDirectives } from './chunk-JB2YYNK6.js';
3
- import { ref, reactive, handleError, nextTick, queuePostFlush, warn, watch, EffectScope, computed, effect, toRaw, flushSync, effectScope, stop, unref, markRaw, watchEffect, shallowRef, setErrorHandler } from './chunk-4T2UIPWX.js';
4
- import { warnDuplicateKey, warn as warn$1, describeElement, warnUnknownComponent, warnAlias, warnRequiredProp } from './chunk-CYN6VLMD.js';
5
- import { parseDuration, debounce, utils_exports, throttle, uid, device, escapeHtml } from './chunk-ZIWLQZZL.js';
6
- import { injectStyle, ensureTokens } from './chunk-GIWKGFGY.js';
7
- import { defineDirective, config, PRIORITY, directives, normalizeComponentName, components, usePlugin } from './chunk-MMLUK37L.js';
8
- import { __publicField } from './chunk-YOZTHZS2.js';
1
+ import { http, HttpError, request } from './chunk-DNIQLT66.js';
2
+ import { stringify, markInitialized, markSkipChildren, destroy, walk, removeQuietly, evaluateIn, addCleanup, markNodeScope, setComponentMounter, closestDirective, magic, readAttr, hasAttr, componentAliases, Scope, queryDirective, parse, evaluate, parseAttribute, originalAttributes, hasDirective, findScope, VoodooRuntimeError, VoodooSyntaxError, allowedGlobals, clearParseCache, tokenize, getScope, stopObserving, refresh, start, magics, rootScope, isInitialized, restoreAttributes, hasDirectives } from './chunk-5E3UZREN.js';
3
+ import { ref, reactive, handleError, nextTick, queuePostFlush, warn, watch, EffectScope, computed, effect, toRaw, flushSync, effectScope, stop, unref, markRaw, watchEffect, shallowRef, setErrorHandler } from './chunk-246ZC2JD.js';
4
+ import { warnDuplicateKey, warn as warn$1, describeElement, warnUnknownComponent, warnAlias, warnRequiredProp } from './chunk-RREZZ4FB.js';
5
+ import { parseDuration, debounce, utils_exports, throttle, uid, device, escapeHtml } from './chunk-F3Z3HMZR.js';
6
+ import { injectStyle, ensureTokens } from './chunk-KQRWQPD6.js';
7
+ import { defineDirective, config, PRIORITY, directives, normalizeComponentName, components, usePlugin } from './chunk-D4DNTWIS.js';
8
+ import { __publicField } from './chunk-2UST7MKN.js';
9
9
 
10
10
  /**
11
- * Voodoo.js v0.7.0
11
+ * Voodoo.js v0.10.1
12
12
  * JavaScript feels like magic.
13
13
  * (c) 2026 Voodoo.js contributors. MIT License.
14
14
  */
@@ -2662,7 +2662,7 @@ var jsonStylesInjected = false;
2662
2662
  function injectJSONStyles() {
2663
2663
  if (jsonStylesInjected) return;
2664
2664
  jsonStylesInjected = true;
2665
- void import('./style-SLQ6PHZK.js').then(({ injectStyle: injectStyle2 }) => {
2665
+ void import('./style-BSEVBI4K.js').then(({ injectStyle: injectStyle2 }) => {
2666
2666
  injectStyle2(
2667
2667
  "json-render",
2668
2668
  `
@@ -2949,7 +2949,7 @@ function data(values) {
2949
2949
  Object.defineProperties(rootScope.data, Object.getOwnPropertyDescriptors(values));
2950
2950
  return rootScope.data;
2951
2951
  }
2952
- var version2 = "0.7.0";
2952
+ var version2 = "0.10.1";
2953
2953
  var core = {
2954
2954
  // Utilities first: Voodoo's own names can override.
2955
2955
  ...utils_exports,
@@ -10271,5 +10271,5 @@ defineDirective(
10271
10271
  );
10272
10272
 
10273
10273
  export { VoodooCollection, alert, allStores, applyMask, cache, clearErrors, clipboard, confirm, cookie, core, createApp, createResource, defineComponent, dialog, efeitos, ensurePalette, enter, fadeIn, fadeOut, fromHtml, hotkey, instances, leave, mask, masks, messages, modal, mountComponent, network, palette, prompt, query, ready, ready2, registerMask, removeStore, screen, serializeForm, session, showFieldError, showFormErrors, slideDown, slideUp, sound, storage, store, storeNames, theme, toast, unmask, url, validate, validator, viewTransition, whenElement, whenReady };
10274
- //# sourceMappingURL=chunk-II3XBOAP.js.map
10275
- //# sourceMappingURL=chunk-II3XBOAP.js.map
10274
+ //# sourceMappingURL=chunk-4MJIS5RZ.js.map
10275
+ //# sourceMappingURL=chunk-4MJIS5RZ.js.map
@@ -1,8 +1,8 @@
1
- import { reactive } from './chunk-4T2UIPWX.js';
2
- import { warnOnce } from './chunk-CYN6VLMD.js';
1
+ import { reactive } from './chunk-246ZC2JD.js';
2
+ import { warnOnce } from './chunk-RREZZ4FB.js';
3
3
 
4
4
  /**
5
- * Voodoo.js v0.7.0
5
+ * Voodoo.js v0.10.1
6
6
  * JavaScript feels like magic.
7
7
  * (c) 2026 Voodoo.js contributors. MIT License.
8
8
  */
@@ -942,5 +942,5 @@ Object.defineProperty(factory, "open", {
942
942
  var socket = factory;
943
943
 
944
944
  export { ENGINE, SIO, createSocket, decodeEngine, decodeSocketIo, devtoolsBus, encodeSocketIo, engineURL, resolveSocketURL, socket, socketSupported };
945
- //# sourceMappingURL=chunk-QO3I7VLJ.js.map
946
- //# sourceMappingURL=chunk-QO3I7VLJ.js.map
945
+ //# sourceMappingURL=chunk-5D7TM3GL.js.map
946
+ //# sourceMappingURL=chunk-5D7TM3GL.js.map
@@ -1,10 +1,10 @@
1
- import { reactive, handleError, EffectScope, effect } from './chunk-4T2UIPWX.js';
2
- import { inDevelopment, warnInvalidExpression, warnUnknownDirective } from './chunk-CYN6VLMD.js';
3
- import { config, directives, components } from './chunk-MMLUK37L.js';
4
- import { __publicField } from './chunk-YOZTHZS2.js';
1
+ import { reactive, handleError, EffectScope, effect } from './chunk-246ZC2JD.js';
2
+ import { inDevelopment, warnInvalidExpression, warnUnknownDirective } from './chunk-RREZZ4FB.js';
3
+ import { config, directives, components } from './chunk-D4DNTWIS.js';
4
+ import { __publicField } from './chunk-2UST7MKN.js';
5
5
 
6
6
  /**
7
- * Voodoo.js v0.7.0
7
+ * Voodoo.js v0.10.1
8
8
  * JavaScript feels like magic.
9
9
  * (c) 2026 Voodoo.js contributors. MIT License.
10
10
  */
@@ -28,6 +28,7 @@ var PUNCTUATORS = [
28
28
  "!==",
29
29
  "**=",
30
30
  "...",
31
+ ">>>",
31
32
  "<<=",
32
33
  ">>=",
33
34
  "&&=",
@@ -50,6 +51,11 @@ var PUNCTUATORS = [
50
51
  "*=",
51
52
  "/=",
52
53
  "%=",
54
+ "&=",
55
+ "|=",
56
+ "^=",
57
+ "<<",
58
+ ">>",
53
59
  "+",
54
60
  "-",
55
61
  "*",
@@ -59,6 +65,10 @@ var PUNCTUATORS = [
59
65
  "<",
60
66
  ">",
61
67
  "=",
68
+ "&",
69
+ "|",
70
+ "^",
71
+ "~",
62
72
  "(",
63
73
  ")",
64
74
  "[",
@@ -122,6 +132,10 @@ function tokenize(source) {
122
132
  raw = "0b";
123
133
  i += 2;
124
134
  while (i < len && /[01_]/.test(source[i])) raw += source[i++];
135
+ } else if (ch === "0" && (source[i + 1] === "o" || source[i + 1] === "O")) {
136
+ raw = "0o";
137
+ i += 2;
138
+ while (i < len && /[0-7_]/.test(source[i])) raw += source[i++];
125
139
  } else {
126
140
  while (i < len && /[0-9_]/.test(source[i])) raw += source[i++];
127
141
  if (source[i] === ".") {
@@ -278,25 +292,31 @@ var BINARY_PRECEDENCE = {
278
292
  "??": 1,
279
293
  "||": 2,
280
294
  "&&": 3,
281
- "==": 6,
282
- "!=": 6,
283
- "===": 6,
284
- "!==": 6,
285
- "<": 7,
286
- ">": 7,
287
- "<=": 7,
288
- ">=": 7,
289
- in: 7,
290
- instanceof: 7,
291
- "+": 9,
292
- "-": 9,
293
- "*": 10,
294
- "/": 10,
295
- "%": 10,
296
- "**": 11
295
+ "|": 4,
296
+ "^": 5,
297
+ "&": 6,
298
+ "==": 7,
299
+ "!=": 7,
300
+ "===": 7,
301
+ "!==": 7,
302
+ "<": 8,
303
+ ">": 8,
304
+ "<=": 8,
305
+ ">=": 8,
306
+ in: 8,
307
+ instanceof: 8,
308
+ "<<": 9,
309
+ ">>": 9,
310
+ ">>>": 9,
311
+ "+": 10,
312
+ "-": 10,
313
+ "*": 11,
314
+ "/": 11,
315
+ "%": 11,
316
+ "**": 12
297
317
  };
298
318
  var ASSIGN_OPS = /* @__PURE__ */ new Set(["=", "+=", "-=", "*=", "/=", "%=", "**=", "&&=", "||=", "??="]);
299
- var UNARY_OPS = /* @__PURE__ */ new Set(["!", "-", "+", "typeof", "void"]);
319
+ var UNARY_OPS = /* @__PURE__ */ new Set(["!", "-", "+", "~", "typeof", "void", "delete"]);
300
320
  var LITERALS = /* @__PURE__ */ Object.assign(/* @__PURE__ */ Object.create(null), {
301
321
  true: true,
302
322
  false: false,
@@ -378,6 +398,13 @@ var Parser = class {
378
398
  * language is an expression.
379
399
  */
380
400
  parseStatement() {
401
+ if (this.peek().type === "ident" && this.peek().value === "return") {
402
+ this.next();
403
+ if (this.isPunct(";") || this.isPunct(",") || this.isPunct("}") || this.peek().type === "eof") {
404
+ return { t: "return", a: null };
405
+ }
406
+ return { t: "return", a: this.parseExpression() };
407
+ }
381
408
  if (this.peek().type === "ident" && this.peek().value === "if" && this.isPunct("(", 1)) {
382
409
  this.next();
383
410
  this.expect("(");
@@ -431,7 +458,7 @@ var Parser = class {
431
458
  if (this.peek().type === "ident" && this.isPunct("=>", 1)) {
432
459
  const param = this.next().value;
433
460
  this.next();
434
- return { t: "arrow", params: [param], body: this.parseArrowBody() };
461
+ return { t: "arrow", params: [{ kind: "id", name: param }], body: this.parseArrowBody() };
435
462
  }
436
463
  if (this.isPunct("(")) {
437
464
  const arrow = this.tryParseParenArrow();
@@ -468,19 +495,108 @@ var Parser = class {
468
495
  const after = this.tokens[i + 1];
469
496
  if (!after || after.type !== "punct" || after.value !== "=>") return null;
470
497
  this.next();
498
+ let params;
499
+ try {
500
+ params = this.parseParamList();
501
+ } catch {
502
+ this.pos = start2;
503
+ return null;
504
+ }
505
+ this.expect("=>");
506
+ return { t: "arrow", params, body: this.parseArrowBody() };
507
+ }
508
+ /** Parameters up to the closing parenthesis, which it consumes. */
509
+ parseParamList() {
471
510
  const params = [];
472
511
  while (!this.isPunct(")")) {
473
- const t = this.next();
474
- if (t.type !== "ident") {
475
- this.pos = start2;
476
- return null;
477
- }
478
- params.push(t.value);
512
+ params.push(this.parseParam());
479
513
  if (this.isPunct(",")) this.next();
514
+ else break;
480
515
  }
481
516
  this.expect(")");
482
- this.expect("=>");
483
- return { t: "arrow", params, body: this.parseArrowBody() };
517
+ return params;
518
+ }
519
+ /**
520
+ * One binding: `x`, `x = 1`, `...xs`, `{ a, b: c = 2 }`, `[a, , b]`.
521
+ *
522
+ * Recursive, so a pattern nests to any depth the way JavaScript's does.
523
+ */
524
+ parseParam() {
525
+ if (this.isPunct("...")) {
526
+ this.next();
527
+ const name = this.next();
528
+ if (name.type !== "ident") {
529
+ throw new VoodooSyntaxError("Expected a name after ...", this.source, name.start);
530
+ }
531
+ return { kind: "rest", name: name.value };
532
+ }
533
+ let param;
534
+ if (this.isPunct("{")) {
535
+ this.next();
536
+ const props = [];
537
+ let rest;
538
+ while (!this.isPunct("}")) {
539
+ if (this.isPunct("...")) {
540
+ this.next();
541
+ const name = this.next();
542
+ if (name.type !== "ident") {
543
+ throw new VoodooSyntaxError("Expected a name after ...", this.source, name.start);
544
+ }
545
+ rest = name.value;
546
+ } else {
547
+ const key = this.next();
548
+ if (key.type !== "ident" && key.type !== "str") {
549
+ throw new VoodooSyntaxError("Expected a property name", this.source, key.start);
550
+ }
551
+ const value = this.isPunct(":") ? (this.next(), this.parseParam()) : { kind: "id", name: key.value };
552
+ if (this.isPunct("=")) {
553
+ this.next();
554
+ value.def = this.parseAssignment();
555
+ }
556
+ props.push({ key: String(key.value), value });
557
+ }
558
+ if (this.isPunct(",")) this.next();
559
+ else break;
560
+ }
561
+ this.expect("}");
562
+ param = { kind: "obj", props, rest };
563
+ } else if (this.isPunct("[")) {
564
+ this.next();
565
+ const elements = [];
566
+ let rest;
567
+ while (!this.isPunct("]")) {
568
+ if (this.isPunct(",")) {
569
+ this.next();
570
+ elements.push(null);
571
+ continue;
572
+ }
573
+ if (this.isPunct("...")) {
574
+ this.next();
575
+ const name = this.next();
576
+ if (name.type !== "ident") {
577
+ throw new VoodooSyntaxError("Expected a name after ...", this.source, name.start);
578
+ }
579
+ rest = name.value;
580
+ } else {
581
+ elements.push(this.parseParam());
582
+ }
583
+ if (this.isPunct(",")) this.next();
584
+ else break;
585
+ }
586
+ this.expect("]");
587
+ param = { kind: "arr", elements, rest };
588
+ } else {
589
+ const name = this.next();
590
+ if (name.type !== "ident") {
591
+ throw new VoodooSyntaxError("Expected a parameter name", this.source, name.start);
592
+ }
593
+ param = { kind: "id", name: name.value };
594
+ }
595
+ if (this.isPunct("=")) {
596
+ this.next();
597
+ param.def = this.parseAssignment();
598
+ }
599
+ return param;
484
600
  }
485
601
  parseConditional() {
486
602
  const test = this.parseBinary(0);
@@ -540,8 +656,57 @@ var Parser = class {
540
656
  }
541
657
  return expr;
542
658
  }
659
+ /**
660
+ * `new X`, `new X(a, b)`, and `new a.b.C(x)`.
661
+ *
662
+ * `new` did not exist here, in the lexer, or in the interpreter. So
663
+ * `new Date(0)` lexed as the identifier `new` followed by `Date(0)`, the
664
+ * parser dropped the dangling identifier, and what ran was `Date(0)`. Called
665
+ * without `new`, `Date` returns a STRING of the current time, so
666
+ * `new Date(0)` produced today's date as text, `new Date(0) instanceof Date`
667
+ * was false, and `new Date(0).getTime()` failed with "getTime is not a
668
+ * function". Three wrong answers, none of them an error.
669
+ *
670
+ * The callee is parsed as a member chain WITHOUT consuming a call, because in
671
+ * JavaScript the argument list binds to the `new`: `new a.b.C(x)` constructs
672
+ * `a.b.C` with `x`, and never calls `a.b.C(x)` and constructs the result. The
673
+ * trailing `(` is then read here, and anything after it, such as
674
+ * `new Date(0).getTime()`, is left to the ordinary member loop below.
675
+ */
676
+ parseNew() {
677
+ this.next();
678
+ const callee = this.parseMemberOnly(this.parsePrimary());
679
+ const args = this.isPunct("(") ? this.parseArguments() : [];
680
+ return { t: "new", callee, args };
681
+ }
682
+ /**
683
+ * Member access only: `.x`, `?.x` and `[x]`, stopping at a call.
684
+ *
685
+ * Used for a `new` callee, where the argument list belongs to the `new`
686
+ * rather than to the expression it is constructing.
687
+ */
688
+ parseMemberOnly(start2) {
689
+ let expr = start2;
690
+ for (; ; ) {
691
+ if (this.isPunct(".")) {
692
+ this.next();
693
+ const prop = this.next();
694
+ if (prop.type !== "ident") {
695
+ throw new VoodooSyntaxError("Invalid property name", this.source, prop.start);
696
+ }
697
+ expr = { t: "member", o: expr, p: { t: "lit", v: prop.value }, computed: false, opt: false };
698
+ } else if (this.isPunct("[")) {
699
+ this.next();
700
+ const p = this.parseExpression();
701
+ this.expect("]");
702
+ expr = { t: "member", o: expr, p, computed: true, opt: false };
703
+ } else {
704
+ return expr;
705
+ }
706
+ }
707
+ }
543
708
  parseCallMember() {
544
- let expr = this.parsePrimary();
709
+ let expr = this.isIdent("new") ? this.parseNew() : this.parsePrimary();
545
710
  for (; ; ) {
546
711
  if (this.isPunct(".")) {
547
712
  this.next();
@@ -606,16 +771,7 @@ var Parser = class {
606
771
  this.next();
607
772
  if (this.peek().type === "ident") this.next();
608
773
  this.expect("(");
609
- const params = [];
610
- while (!this.isPunct(")")) {
611
- const param = this.next();
612
- if (param.type !== "ident") {
613
- throw new VoodooSyntaxError("Expected a parameter name", this.source, param.start);
614
- }
615
- params.push(param.value);
616
- if (this.isPunct(",")) this.next();
617
- }
618
- this.expect(")");
774
+ const params = this.parseParamList();
619
775
  return { t: "arrow", params, body: this.parseArrowBody() };
620
776
  }
621
777
  if (t.type === "num" || t.type === "str") {
@@ -720,16 +876,7 @@ var Parser = class {
720
876
  props.push({ key, value: this.parseAssignment() });
721
877
  } else if (this.isPunct("(")) {
722
878
  this.next();
723
- const params = [];
724
- while (!this.isPunct(")")) {
725
- const param = this.next();
726
- if (param.type !== "ident") {
727
- throw new VoodooSyntaxError("Expected a parameter name", this.source, param.start);
728
- }
729
- params.push(param.value);
730
- if (this.isPunct(",")) this.next();
731
- }
732
- this.expect(")");
879
+ const params = this.parseParamList();
733
880
  props.push({ key, value: { t: "method", params, body: this.parseArrowBody() } });
734
881
  } else {
735
882
  props.push({ key, value: { t: "id", n: key } });
@@ -832,6 +979,14 @@ Expression: ${expression}` : message);
832
979
  }
833
980
  };
834
981
  var SPREAD = /* @__PURE__ */ Symbol("spread");
982
+ var ReturnSignal = class {
983
+ constructor(value) {
984
+ __publicField(this, "value", value);
985
+ }
986
+ };
987
+ function unwrap(value) {
988
+ return value instanceof ReturnSignal ? value.value : value;
989
+ }
835
990
  var BLOCKED_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
836
991
  function chaveBloqueada(key) {
837
992
  return typeof key === "string" && BLOCKED_KEYS.has(key);
@@ -877,6 +1032,19 @@ function evaluate(node, scope) {
877
1032
  );
878
1033
  return obj[key];
879
1034
  }
1035
+ case "new": {
1036
+ const target = evaluate(node.callee, scope);
1037
+ if (typeof target !== "function") {
1038
+ throw new VoodooRuntimeError(
1039
+ `Cannot construct ${stringify(target)}: it is not a constructor`
1040
+ );
1041
+ }
1042
+ if (target === Function) {
1043
+ throw new VoodooRuntimeError("Cannot construct Function: expressions never compile code");
1044
+ }
1045
+ const args = evalArgs(node.args, scope);
1046
+ return Reflect.construct(target, args);
1047
+ }
880
1048
  case "call": {
881
1049
  let thisArg;
882
1050
  let fn;
@@ -924,6 +1092,19 @@ function evaluate(node, scope) {
924
1092
  }
925
1093
  case "unary": {
926
1094
  if (node.op === "...") return { [SPREAD]: evaluate(node.a, scope) };
1095
+ if (node.op === "delete") {
1096
+ if (node.a.t !== "member") {
1097
+ throw new VoodooRuntimeError(
1098
+ "delete needs a property, as in `delete user.name` or `delete list[0]`"
1099
+ );
1100
+ }
1101
+ const owner = evaluate(node.a.o, scope);
1102
+ if (owner == null) return true;
1103
+ const key = checkKey(
1104
+ node.a.computed ? evaluate(node.a.p, scope) : node.a.p.v
1105
+ );
1106
+ return delete owner[key];
1107
+ }
927
1108
  if (node.op === "typeof") {
928
1109
  if (node.a.t === "id") {
929
1110
  if (chaveBloqueada(node.a.n)) return "undefined";
@@ -941,6 +1122,8 @@ function evaluate(node, scope) {
941
1122
  return -v;
942
1123
  case "+":
943
1124
  return +v;
1125
+ case "~":
1126
+ return ~v;
944
1127
  case "void":
945
1128
  return void 0;
946
1129
  }
@@ -988,6 +1171,23 @@ function evaluate(node, scope) {
988
1171
  return l in r;
989
1172
  case "instanceof":
990
1173
  return l instanceof r;
1174
+ // The bitwise operators coerce through ToInt32, and `>>>` through
1175
+ // ToUint32, which is why the two shifts disagree for negatives:
1176
+ // `-1 >> 0` is -1 and `-1 >>> 0` is 4294967295. Applying the JavaScript
1177
+ // operator directly gets that for free; hand-rolling the coercion is
1178
+ // how an implementation ends up subtly wrong on exactly those cases.
1179
+ case "&":
1180
+ return l & r;
1181
+ case "|":
1182
+ return l | r;
1183
+ case "^":
1184
+ return l ^ r;
1185
+ case "<<":
1186
+ return l << r;
1187
+ case ">>":
1188
+ return l >> r;
1189
+ case ">>>":
1190
+ return l >>> r;
991
1191
  }
992
1192
  throw new VoodooRuntimeError(`Unsupported operator: ${node.op}`);
993
1193
  }
@@ -1045,21 +1245,16 @@ function evaluate(node, scope) {
1045
1245
  const methodParams = node.params;
1046
1246
  const methodBody = node.body;
1047
1247
  return function(...args) {
1048
- const vars = {};
1049
- for (let i = 0; i < methodParams.length; i++) vars[methodParams[i]] = args[i];
1248
+ const vars = bindParams(methodParams, args, scope);
1050
1249
  const owner = this;
1051
1250
  const base = owner !== null && typeof owner === "object" ? scope.child(owner) : scope;
1052
- return evaluate(methodBody, base.child(vars));
1251
+ return unwrap(evaluate(methodBody, base.child(vars)));
1053
1252
  };
1054
1253
  }
1055
1254
  case "arrow": {
1056
1255
  const params = node.params;
1057
1256
  const body = node.body;
1058
- return (...args) => {
1059
- const vars = {};
1060
- for (let i = 0; i < params.length; i++) vars[params[i]] = args[i];
1061
- return evaluate(body, scope.child(vars));
1062
- };
1257
+ return (...args) => unwrap(evaluate(body, scope.child(bindParams(params, args, scope))));
1063
1258
  }
1064
1259
  case "obj": {
1065
1260
  const out = {};
@@ -1097,14 +1292,65 @@ function evaluate(node, scope) {
1097
1292
  }
1098
1293
  return out;
1099
1294
  }
1295
+ case "return":
1296
+ return new ReturnSignal(node.a ? evaluate(node.a, scope) : void 0);
1100
1297
  case "seq": {
1101
1298
  let last;
1102
- for (const stmt of node.body) last = evaluate(stmt, scope);
1299
+ for (const stmt of node.body) {
1300
+ last = evaluate(stmt, scope);
1301
+ if (last instanceof ReturnSignal) return last;
1302
+ }
1103
1303
  return last;
1104
1304
  }
1105
1305
  }
1106
1306
  throw new VoodooRuntimeError(`Unknown node: ${node.t}`);
1107
1307
  }
1308
+ function bindParam(param, value, vars, scope) {
1309
+ if (param.kind === "rest") {
1310
+ vars[param.name] = value;
1311
+ return;
1312
+ }
1313
+ if (param.def !== void 0 && value === void 0) {
1314
+ value = evaluate(param.def, scope.child(vars));
1315
+ }
1316
+ if (param.kind === "id") {
1317
+ vars[param.name] = value;
1318
+ return;
1319
+ }
1320
+ if (param.kind === "obj") {
1321
+ if (value == null) {
1322
+ throw new VoodooRuntimeError(
1323
+ `Cannot destructure ${value === null ? "null" : "undefined"}`
1324
+ );
1325
+ }
1326
+ const taken = /* @__PURE__ */ new Set();
1327
+ for (const { key, value: inner } of param.props) {
1328
+ taken.add(key);
1329
+ bindParam(inner, value[checkKey(key)], vars, scope);
1330
+ }
1331
+ if (param.rest) {
1332
+ const rest = {};
1333
+ for (const key of Object.keys(value)) {
1334
+ if (!taken.has(key)) rest[key] = value[key];
1335
+ }
1336
+ vars[param.rest] = rest;
1337
+ }
1338
+ return;
1339
+ }
1340
+ const items = Array.isArray(value) ? value : Array.from(value);
1341
+ param.elements.forEach((element, index) => {
1342
+ if (element) bindParam(element, items[index], vars, scope);
1343
+ });
1344
+ if (param.rest) vars[param.rest] = items.slice(param.elements.length);
1345
+ }
1346
+ function bindParams(params, args, scope) {
1347
+ const vars = {};
1348
+ for (let i = 0; i < params.length; i++) {
1349
+ const param = params[i];
1350
+ bindParam(param, param.kind === "rest" ? args.slice(i) : args[i], vars, scope);
1351
+ }
1352
+ return vars;
1353
+ }
1108
1354
  function evalArgs(args, scope) {
1109
1355
  const out = [];
1110
1356
  for (const arg of args) {
@@ -1797,12 +2043,27 @@ function resolveComponentTag(tagName) {
1797
2043
  var componentAliases = /* @__PURE__ */ new Map();
1798
2044
  var started = false;
1799
2045
  var observer = null;
2046
+ var startHooks = [];
2047
+ function onStart(hook) {
2048
+ startHooks.push(hook);
2049
+ }
2050
+ function runPhase(target, after) {
2051
+ for (const hook of startHooks) {
2052
+ try {
2053
+ hook(target, after);
2054
+ } catch (error) {
2055
+ console.error("[Voodoo] a start hook failed", error);
2056
+ }
2057
+ }
2058
+ }
1800
2059
  function start(root) {
1801
2060
  if (typeof document === "undefined") return;
1802
2061
  const target = root ?? config.root ?? document.body;
1803
2062
  if (!target) return;
1804
2063
  Object.assign(allowedGlobals, config.globals);
2064
+ runPhase(target, false);
1805
2065
  walk(target, rootScope);
2066
+ runPhase(target, true);
1806
2067
  if (!started) {
1807
2068
  started = true;
1808
2069
  if (config.autoDiscover) observeDOM(target);
@@ -1840,6 +2101,6 @@ function refresh(root) {
1840
2101
  walk(root ?? document.body, root ? findScope(root.parentNode) : rootScope);
1841
2102
  }
1842
2103
 
1843
- export { Scope, VoodooRuntimeError, VoodooSyntaxError, addCleanup, allowedGlobals, clearParseCache, closestDirective, collectDirectives, componentAliases, destroy, evaluate, evaluateIn, findScope, getEffectScopes, getScope, hadDirectives, hasAttr, hasDirective, hasDirectives, isInitialized, magic, magics, markInitialized, markNodeScope, markSkipChildren, originalAttributes, parse, parseAttribute, queryDirective, readAttr, refresh, removeQuietly, restoreAttributes, rootScope, setComponentMounter, start, stopObserving, stringify, tokenize, walk };
1844
- //# sourceMappingURL=chunk-JB2YYNK6.js.map
1845
- //# sourceMappingURL=chunk-JB2YYNK6.js.map
2104
+ export { Scope, VoodooRuntimeError, VoodooSyntaxError, addCleanup, allowedGlobals, clearParseCache, closestDirective, collectDirectives, componentAliases, destroy, evaluate, evaluateIn, findScope, getEffectScopes, getScope, hadDirectives, hasAttr, hasDirective, hasDirectives, isInitialized, magic, magics, markInitialized, markNodeScope, markSkipChildren, onStart, originalAttributes, parse, parseAttribute, queryDirective, readAttr, refresh, removeQuietly, restoreAttributes, rootScope, setComponentMounter, start, stopObserving, stringify, tokenize, unwrap, walk };
2105
+ //# sourceMappingURL=chunk-5E3UZREN.js.map
2106
+ //# sourceMappingURL=chunk-5E3UZREN.js.map