round-core 0.0.7 → 0.0.9

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 (76) hide show
  1. package/README.md +62 -41
  2. package/dist/index.d.ts +341 -341
  3. package/dist/index.js +211 -192
  4. package/dist/vite-plugin.js +52 -3
  5. package/package.json +7 -4
  6. package/.github/workflows/benchmarks.yml +0 -44
  7. package/Round.png +0 -0
  8. package/benchmarks/apps/react/index.html +0 -9
  9. package/benchmarks/apps/react/main.jsx +0 -25
  10. package/benchmarks/apps/react/vite.config.js +0 -12
  11. package/benchmarks/apps/round/index.html +0 -11
  12. package/benchmarks/apps/round/main.jsx +0 -22
  13. package/benchmarks/apps/round/vite.config.js +0 -15
  14. package/benchmarks/bun.lock +0 -497
  15. package/benchmarks/dist-bench/react/assets/index-9KGqIPOU.js +0 -8
  16. package/benchmarks/dist-bench/react/index.html +0 -10
  17. package/benchmarks/dist-bench/round/assets/index-CBBIRhox.js +0 -52
  18. package/benchmarks/dist-bench/round/index.html +0 -8
  19. package/benchmarks/package.json +0 -22
  20. package/benchmarks/scripts/measure-build.js +0 -64
  21. package/benchmarks/tests/runtime.bench.js +0 -51
  22. package/benchmarks/vitest.config.js +0 -8
  23. package/bun.lock +0 -425
  24. package/cli.js +0 -2
  25. package/extension/.vscodeignore +0 -5
  26. package/extension/LICENSE +0 -21
  27. package/extension/cgmanifest.json +0 -45
  28. package/extension/extension.js +0 -163
  29. package/extension/images/round-config-dark.svg +0 -10
  30. package/extension/images/round-config-light.svg +0 -10
  31. package/extension/images/round-dark.svg +0 -10
  32. package/extension/images/round-light.svg +0 -10
  33. package/extension/javascript-language-configuration.json +0 -241
  34. package/extension/package-lock.json +0 -97
  35. package/extension/package.json +0 -119
  36. package/extension/package.nls.json +0 -4
  37. package/extension/round-0.1.0.vsix +0 -0
  38. package/extension/round-lsp/package-lock.json +0 -185
  39. package/extension/round-lsp/package.json +0 -21
  40. package/extension/round-lsp/src/round-transformer-lsp.js +0 -248
  41. package/extension/round-lsp/src/server.js +0 -396
  42. package/extension/snippets/javascript.code-snippets +0 -266
  43. package/extension/snippets/round.code-snippets +0 -109
  44. package/extension/syntaxes/JavaScript.tmLanguage.json +0 -6001
  45. package/extension/syntaxes/JavaScriptReact.tmLanguage.json +0 -6066
  46. package/extension/syntaxes/Readme.md +0 -12
  47. package/extension/syntaxes/Regular Expressions (JavaScript).tmLanguage +0 -237
  48. package/extension/syntaxes/Round.tmLanguage.json +0 -290
  49. package/extension/syntaxes/RoundInject.tmLanguage.json +0 -20
  50. package/extension/tags-language-configuration.json +0 -152
  51. package/extension/temp_astro/package-lock.json +0 -912
  52. package/extension/temp_astro/package.json +0 -16
  53. package/extension/types/round-core.d.ts +0 -326
  54. package/index.js +0 -2
  55. package/logo.svg +0 -10
  56. package/src/cli.js +0 -608
  57. package/src/compiler/index.js +0 -2
  58. package/src/compiler/transformer.js +0 -443
  59. package/src/compiler/vite-plugin.js +0 -472
  60. package/src/index.d.ts +0 -341
  61. package/src/index.js +0 -45
  62. package/src/runtime/context.js +0 -101
  63. package/src/runtime/dom.js +0 -403
  64. package/src/runtime/error-boundary.js +0 -48
  65. package/src/runtime/error-reporter.js +0 -13
  66. package/src/runtime/error-store.js +0 -85
  67. package/src/runtime/errors.js +0 -152
  68. package/src/runtime/lifecycle.js +0 -142
  69. package/src/runtime/markdown.js +0 -72
  70. package/src/runtime/router.js +0 -468
  71. package/src/runtime/signals.js +0 -548
  72. package/src/runtime/store.js +0 -215
  73. package/src/runtime/suspense.js +0 -128
  74. package/vite.config.build.js +0 -48
  75. package/vite.config.js +0 -10
  76. package/vitest.config.js +0 -8
package/dist/index.js CHANGED
@@ -37,13 +37,11 @@ function onMount(fn) {
37
37
  if (component) {
38
38
  component.mountHooks.push(fn);
39
39
  } else {
40
- setTimeout(() => {
41
- try {
42
- fn();
43
- } catch (e) {
44
- reportErrorSafe(e, { phase: "onMount" });
45
- }
46
- }, 0);
40
+ try {
41
+ fn();
42
+ } catch (e) {
43
+ reportErrorSafe(e, { phase: "onMount" });
44
+ }
47
45
  }
48
46
  }
49
47
  function onUnmount(fn) {
@@ -145,135 +143,180 @@ const Lifecycle = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePro
145
143
  triggerUpdate,
146
144
  unmountComponent
147
145
  }, Symbol.toStringTag, { value: "Module" }));
148
- let context = [];
146
+ let context = null;
147
+ let batchCount = 0;
148
+ let pendingEffects = [];
149
+ let globalVersion = 0;
149
150
  function isPromiseLike$2(v) {
150
151
  return v && (typeof v === "object" || typeof v === "function") && typeof v.then === "function";
151
152
  }
152
- function subscribe(running, subscriptions) {
153
- subscriptions.add(running);
154
- running.dependencies.add(subscriptions);
153
+ function isSignalLike(v) {
154
+ return typeof v === "function" && typeof v.peek === "function" && "value" in v;
155
155
  }
156
156
  function untrack(fn) {
157
- context.push(null);
157
+ const prev = context;
158
+ context = null;
158
159
  try {
159
160
  return typeof fn === "function" ? fn() : void 0;
160
161
  } finally {
161
- context.pop();
162
+ context = prev;
163
+ }
164
+ }
165
+ function batch(fn) {
166
+ batchCount++;
167
+ try {
168
+ return fn();
169
+ } finally {
170
+ if (--batchCount === 0) {
171
+ const effects = pendingEffects;
172
+ pendingEffects = [];
173
+ for (let i = 0; i < effects.length; i++) {
174
+ effects[i].queued = false;
175
+ effects[i].run();
176
+ }
177
+ }
178
+ }
179
+ }
180
+ function subscribe(sub, dep) {
181
+ let link = sub.deps;
182
+ while (link) {
183
+ if (link.dep === dep) return;
184
+ link = link.nextDep;
185
+ }
186
+ link = {
187
+ sub,
188
+ dep,
189
+ nextSub: dep.subs,
190
+ prevSub: null,
191
+ nextDep: sub.deps,
192
+ prevDep: null
193
+ };
194
+ if (dep.subs) dep.subs.prevSub = link;
195
+ dep.subs = link;
196
+ if (sub.deps) sub.deps.prevDep = link;
197
+ sub.deps = link;
198
+ }
199
+ function cleanup(sub) {
200
+ let link = sub.deps;
201
+ while (link) {
202
+ const { dep, prevSub, nextSub } = link;
203
+ if (prevSub) prevSub.nextSub = nextSub;
204
+ else dep.subs = nextSub;
205
+ if (nextSub) nextSub.prevSub = prevSub;
206
+ link = link.nextDep;
207
+ }
208
+ sub.deps = null;
209
+ }
210
+ function notify(dep) {
211
+ let link = dep.subs;
212
+ while (link) {
213
+ const sub = link.sub;
214
+ if (sub.isComputed) {
215
+ sub.version = -1;
216
+ notify(sub);
217
+ } else {
218
+ if (batchCount > 0) {
219
+ if (!sub.queued) {
220
+ sub.queued = true;
221
+ pendingEffects.push(sub);
222
+ }
223
+ } else {
224
+ sub.run();
225
+ }
226
+ }
227
+ link = link.nextSub;
162
228
  }
163
229
  }
164
230
  function effect(arg1, arg2, arg3) {
165
- let callback;
166
- let explicitDeps = null;
167
- let options = { onLoad: true };
231
+ let callback, explicitDeps = null, options = { onLoad: true };
168
232
  let owner = getCurrentComponent();
169
233
  if (typeof arg1 === "function") {
170
234
  callback = arg1;
171
- if (arg2 && typeof arg2 === "object") {
172
- options = { ...options, ...arg2 };
173
- }
235
+ if (arg2 && typeof arg2 === "object") options = { ...options, ...arg2 };
174
236
  } else {
175
237
  explicitDeps = arg1;
176
238
  callback = arg2;
177
- if (arg3 && typeof arg3 === "object") {
178
- options = { ...options, ...arg3 };
179
- }
239
+ if (arg3 && typeof arg3 === "object") options = { ...options, ...arg3 };
180
240
  }
181
- const execute = () => {
182
- if (typeof execute._cleanup === "function") {
183
- try {
184
- execute._cleanup();
185
- } catch (e) {
186
- const name = owner ? owner.name ?? "Anonymous" : null;
187
- reportErrorSafe(e, { phase: "effect.cleanup", component: name });
188
- }
189
- execute._cleanup = null;
190
- }
191
- cleanup(execute);
192
- context.push(execute);
193
- try {
194
- if (explicitDeps) {
195
- if (Array.isArray(explicitDeps)) {
196
- explicitDeps.forEach((dep) => {
197
- if (typeof dep === "function") dep();
198
- });
199
- } else if (typeof explicitDeps === "function") {
200
- explicitDeps();
241
+ const sub = {
242
+ deps: null,
243
+ queued: false,
244
+ run() {
245
+ if (this._cleanup) {
246
+ try {
247
+ this._cleanup();
248
+ } catch (e) {
249
+ reportErrorSafe(e, { phase: "effect.cleanup", component: owner?.name });
201
250
  }
251
+ this._cleanup = null;
202
252
  }
203
- if (typeof callback === "function") {
204
- const res = callback();
205
- if (typeof res === "function") {
206
- execute._cleanup = res;
253
+ cleanup(this);
254
+ const prev = context;
255
+ context = this;
256
+ try {
257
+ if (explicitDeps) {
258
+ if (Array.isArray(explicitDeps)) {
259
+ for (let i = 0; i < explicitDeps.length; i++) {
260
+ const d = explicitDeps[i];
261
+ if (typeof d === "function") d();
262
+ }
263
+ } else if (typeof explicitDeps === "function") {
264
+ explicitDeps();
265
+ }
207
266
  }
267
+ const res = callback();
268
+ if (typeof res === "function") this._cleanup = res;
269
+ if (owner?.isMounted) triggerUpdate(owner);
270
+ } catch (e) {
271
+ if (!isPromiseLike$2(e)) reportErrorSafe(e, { phase: "effect", component: owner?.name });
272
+ else throw e;
273
+ } finally {
274
+ context = prev;
208
275
  }
209
- if (owner && owner.isMounted) triggerUpdate(owner);
210
- } catch (e) {
211
- if (isPromiseLike$2(e)) throw e;
212
- const name = owner ? owner.name ?? "Anonymous" : null;
213
- reportErrorSafe(e, { phase: "effect", component: name });
214
- } finally {
215
- context.pop();
216
- }
276
+ },
277
+ _cleanup: null
217
278
  };
218
- execute.dependencies = /* @__PURE__ */ new Set();
219
- execute._cleanup = null;
220
- if (options.onLoad) {
221
- onMount(execute);
222
- } else {
223
- execute();
224
- }
225
- return () => {
226
- if (typeof execute._cleanup === "function") {
279
+ const dispose = () => {
280
+ if (sub._cleanup) {
227
281
  try {
228
- execute._cleanup();
282
+ sub._cleanup();
229
283
  } catch (e) {
230
- const name = owner ? owner.name ?? "Anonymous" : null;
231
- reportErrorSafe(e, { phase: "effect.cleanup", component: name });
232
284
  }
285
+ sub._cleanup = null;
233
286
  }
234
- execute._cleanup = null;
235
- cleanup(execute);
287
+ cleanup(sub);
236
288
  };
237
- }
238
- function cleanup(running) {
239
- running.dependencies.forEach((dep) => dep.delete(running));
240
- running.dependencies.clear();
289
+ if (options.onLoad) {
290
+ onMount(() => sub.run());
291
+ } else {
292
+ sub.run();
293
+ }
294
+ return dispose;
241
295
  }
242
296
  function defineBindMarkerIfNeeded(source, target) {
243
297
  if (source && source.bind === true) {
244
298
  try {
245
- Object.defineProperty(target, "bind", {
246
- enumerable: true,
247
- configurable: false,
248
- writable: false,
249
- value: true
250
- });
299
+ Object.defineProperty(target, "bind", { enumerable: true, value: true, configurable: true });
251
300
  } catch {
252
- try {
253
- target.bind = true;
254
- } catch {
255
- }
301
+ target.bind = true;
256
302
  }
257
303
  }
258
304
  }
259
305
  function attachHelpers(s) {
260
306
  if (!s || typeof s !== "function") return s;
261
307
  if (typeof s.transform === "function" && typeof s.validate === "function" && typeof s.$pick === "function") return s;
262
- s.$pick = (p) => {
263
- return pick(s, p);
264
- };
308
+ s.$pick = (p) => pick(s, p);
265
309
  s.transform = (fromInput, toOutput) => {
266
310
  const fromFn = typeof fromInput === "function" ? fromInput : (v) => v;
267
311
  const toFn = typeof toOutput === "function" ? toOutput : (v) => v;
268
312
  const wrapped = function(...args) {
269
- if (args.length > 0) {
270
- return s(fromFn(args[0]));
271
- }
313
+ if (args.length > 0) return s(fromFn(args[0]));
272
314
  return toFn(s());
273
315
  };
274
316
  wrapped.peek = () => toFn(s.peek());
275
317
  Object.defineProperty(wrapped, "value", {
276
318
  enumerable: true,
319
+ configurable: true,
277
320
  get() {
278
321
  return wrapped.peek();
279
322
  },
@@ -287,8 +330,8 @@ function attachHelpers(s) {
287
330
  s.validate = (validator, options = {}) => {
288
331
  const validateFn = typeof validator === "function" ? validator : null;
289
332
  const error = signal(null);
290
- const validateOn = options && typeof options === "object" && typeof options.validateOn === "string" ? options.validateOn : "input";
291
- const validateInitial = Boolean(options && typeof options === "object" && options.validateInitial);
333
+ const validateOn = options?.validateOn || "input";
334
+ const validateInitial = !!options?.validateInitial;
292
335
  const wrapped = function(...args) {
293
336
  if (args.length > 0) {
294
337
  const next = args[0];
@@ -303,11 +346,7 @@ function attachHelpers(s) {
303
346
  error(null);
304
347
  return s(next);
305
348
  }
306
- if (typeof res === "string" && res.length) {
307
- error(res);
308
- } else {
309
- error("Invalid value");
310
- }
349
+ error(typeof res === "string" && res.length ? res : "Invalid value");
311
350
  return s.peek();
312
351
  }
313
352
  error(null);
@@ -331,13 +370,13 @@ function attachHelpers(s) {
331
370
  error(null);
332
371
  return true;
333
372
  }
334
- if (typeof res === "string" && res.length) error(res);
335
- else error("Invalid value");
373
+ error(typeof res === "string" && res.length ? res : "Invalid value");
336
374
  return false;
337
375
  };
338
376
  wrapped.peek = () => s.peek();
339
377
  Object.defineProperty(wrapped, "value", {
340
378
  enumerable: true,
379
+ configurable: true,
341
380
  get() {
342
381
  return wrapped.peek();
343
382
  },
@@ -359,66 +398,50 @@ function attachHelpers(s) {
359
398
  return s;
360
399
  }
361
400
  function signal(initialValue) {
362
- let value = initialValue;
363
- const subscriptions = /* @__PURE__ */ new Set();
364
- const read = () => {
365
- const running = context[context.length - 1];
366
- if (running) {
367
- subscribe(running, subscriptions);
368
- }
369
- return value;
401
+ const dep = {
402
+ value: initialValue,
403
+ version: 0,
404
+ subs: null
370
405
  };
371
- const peek = () => value;
372
- const write = (newValue) => {
373
- if (value !== newValue) {
374
- value = newValue;
375
- [...subscriptions].forEach((sub) => sub());
376
- }
377
- return value;
378
- };
379
- const signal2 = function(...args) {
380
- if (args.length > 0) {
381
- return write(args[0]);
406
+ const s = function(newValue) {
407
+ if (arguments.length > 0) {
408
+ if (dep.value !== newValue) {
409
+ dep.value = newValue;
410
+ dep.version = ++globalVersion;
411
+ notify(dep);
412
+ }
413
+ return dep.value;
382
414
  }
383
- return read();
415
+ if (context) subscribe(context, dep);
416
+ return dep.value;
384
417
  };
385
- Object.defineProperty(signal2, "value", {
418
+ s.peek = () => dep.value;
419
+ Object.defineProperty(s, "value", {
386
420
  enumerable: true,
421
+ configurable: true,
387
422
  get() {
388
- return peek();
423
+ return s();
389
424
  },
390
425
  set(v) {
391
- write(v);
426
+ s(v);
392
427
  }
393
428
  });
394
- signal2.peek = peek;
395
- return attachHelpers(signal2);
429
+ return attachHelpers(s);
396
430
  }
397
431
  function bindable(initialValue) {
398
432
  const s = signal(initialValue);
399
433
  try {
400
- Object.defineProperty(s, "bind", {
401
- enumerable: true,
402
- configurable: false,
403
- writable: false,
404
- value: true
405
- });
434
+ Object.defineProperty(s, "bind", { enumerable: true, value: true, configurable: true });
406
435
  } catch {
407
- try {
408
- s.bind = true;
409
- } catch {
410
- }
436
+ s.bind = true;
411
437
  }
412
438
  return attachHelpers(s);
413
439
  }
414
- function isSignalLike(v) {
415
- return typeof v === "function" && typeof v.peek === "function" && "value" in v;
416
- }
417
440
  function getIn(obj, path) {
418
441
  let cur = obj;
419
- for (const key of path) {
442
+ for (let i = 0; i < path.length; i++) {
420
443
  if (cur == null) return void 0;
421
- cur = cur[key];
444
+ cur = cur[path[i]];
422
445
  }
423
446
  return cur;
424
447
  }
@@ -445,9 +468,7 @@ function parsePath(path) {
445
468
  return [String(path)];
446
469
  }
447
470
  function pick(root, path) {
448
- if (!isSignalLike(root)) {
449
- throw new Error("[round] pick(root, path) expects root to be a signal (use bindable.object(...) or signal({...})).");
450
- }
471
+ if (!isSignalLike(root)) throw new Error("[round] pick() expects a signal.");
451
472
  const pathArr = parsePath(path);
452
473
  const view = function(...args) {
453
474
  if (args.length > 0) {
@@ -460,6 +481,7 @@ function pick(root, path) {
460
481
  view.peek = () => getIn(root.peek(), pathArr);
461
482
  Object.defineProperty(view, "value", {
462
483
  enumerable: true,
484
+ configurable: true,
463
485
  get() {
464
486
  return view.peek();
465
487
  },
@@ -469,17 +491,9 @@ function pick(root, path) {
469
491
  });
470
492
  if (root.bind === true) {
471
493
  try {
472
- Object.defineProperty(view, "bind", {
473
- enumerable: true,
474
- configurable: false,
475
- writable: false,
476
- value: true
477
- });
494
+ Object.defineProperty(view, "bind", { enumerable: true, value: true, configurable: true });
478
495
  } catch {
479
- try {
480
- view.bind = true;
481
- } catch {
482
- }
496
+ view.bind = true;
483
497
  }
484
498
  }
485
499
  return view;
@@ -489,21 +503,14 @@ function createBindableObjectProxy(root, basePath) {
489
503
  const handler = {
490
504
  get(_target, prop) {
491
505
  if (prop === Symbol.toStringTag) return "BindableObject";
492
- if (prop === Symbol.iterator) return void 0;
493
506
  if (prop === "peek") return () => basePath.length ? pick(root, basePath).peek() : root.peek();
494
507
  if (prop === "value") return basePath.length ? pick(root, basePath).peek() : root.peek();
495
508
  if (prop === "bind") return true;
496
509
  if (prop === "$pick") {
497
- return (p) => {
498
- const nextPath2 = basePath.concat(parsePath(p));
499
- return createBindableObjectProxy(root, nextPath2);
500
- };
510
+ return (p) => createBindableObjectProxy(root, basePath.concat(parsePath(p)));
501
511
  }
502
512
  if (prop === "_root") return root;
503
513
  if (prop === "_path") return basePath.slice();
504
- if (prop === "call" || prop === "apply") {
505
- return Reflect.get(_target, prop);
506
- }
507
514
  const key = String(prop);
508
515
  const nextPath = basePath.concat(key);
509
516
  const cacheKey = nextPath.join(".");
@@ -535,44 +542,25 @@ function createBindableObjectProxy(root, basePath) {
535
542
  return true;
536
543
  },
537
544
  has(_target, prop) {
538
- try {
539
- if (Reflect.has(_target, prop)) return true;
540
- } catch {
541
- }
545
+ if (prop === "peek" || prop === "value" || prop === "bind" || prop === "$pick") return true;
542
546
  const v = basePath.length ? pick(root, basePath).peek() : root.peek();
543
547
  return v != null && Object.prototype.hasOwnProperty.call(v, prop);
544
548
  }
545
549
  };
546
550
  const fn = function(...args) {
547
- if (args.length > 0) {
548
- if (basePath.length) return pick(root, basePath)(args[0]);
549
- return root(args[0]);
550
- }
551
- if (basePath.length) return pick(root, basePath)();
552
- return root();
551
+ if (args.length > 0) return basePath.length ? pick(root, basePath)(args[0]) : root(args[0]);
552
+ return basePath.length ? pick(root, basePath)() : root();
553
553
  };
554
554
  fn.peek = () => basePath.length ? pick(root, basePath).peek() : root.peek();
555
- Object.defineProperty(fn, "value", {
556
- enumerable: true,
557
- get() {
558
- return fn.peek();
559
- },
560
- set(v) {
561
- fn(v);
562
- }
563
- });
555
+ Object.defineProperty(fn, "value", { enumerable: true, configurable: true, get() {
556
+ return fn.peek();
557
+ }, set(v) {
558
+ fn(v);
559
+ } });
564
560
  try {
565
- Object.defineProperty(fn, "bind", {
566
- enumerable: true,
567
- configurable: false,
568
- writable: false,
569
- value: true
570
- });
561
+ Object.defineProperty(fn, "bind", { enumerable: true, value: true, configurable: true });
571
562
  } catch {
572
- try {
573
- fn.bind = true;
574
- } catch {
575
- }
563
+ fn.bind = true;
576
564
  }
577
565
  return new Proxy(fn, handler);
578
566
  }
@@ -581,14 +569,44 @@ bindable.object = function(initialObject = {}) {
581
569
  return createBindableObjectProxy(root, []);
582
570
  };
583
571
  function derive(fn) {
584
- const derived = signal();
585
- effect(() => {
586
- derived(fn());
587
- }, { onLoad: false });
588
- return () => derived();
572
+ const dep = {
573
+ fn,
574
+ value: void 0,
575
+ version: -1,
576
+ depsVersion: -1,
577
+ subs: null,
578
+ deps: null,
579
+ isComputed: true,
580
+ run() {
581
+ cleanup(this);
582
+ const prev = context;
583
+ context = this;
584
+ try {
585
+ this.value = this.fn();
586
+ this.depsVersion = globalVersion;
587
+ this.version = ++globalVersion;
588
+ } finally {
589
+ context = prev;
590
+ }
591
+ }
592
+ };
593
+ const s = function() {
594
+ if (dep.version === -1 || dep.depsVersion < globalVersion) dep.run();
595
+ if (context) subscribe(context, dep);
596
+ return dep.value;
597
+ };
598
+ s.peek = () => {
599
+ if (dep.version === -1 || dep.depsVersion < globalVersion) dep.run();
600
+ return dep.value;
601
+ };
602
+ Object.defineProperty(s, "value", { enumerable: true, configurable: true, get() {
603
+ return s();
604
+ } });
605
+ return attachHelpers(s);
589
606
  }
590
607
  const Signals = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
591
608
  __proto__: null,
609
+ batch,
592
610
  bindable,
593
611
  derive,
594
612
  effect,
@@ -1980,6 +1998,7 @@ export {
1980
1998
  Route,
1981
1999
  Suspense,
1982
2000
  SuspenseContext,
2001
+ batch,
1983
2002
  bindContext,
1984
2003
  bindable,
1985
2004
  captureContext,
@@ -202,7 +202,7 @@ function transform(code) {
202
202
  const block = parseBlock(result, blockStart);
203
203
  if (!block) break;
204
204
  const content = result.substring(block.start + 1, block.end);
205
- const replacement = `{${list}.map(${item} => (<Fragment>${content}</Fragment>))}`;
205
+ const replacement = `{(() => ${list}.map(${item} => (<Fragment>${content}</Fragment>)))}`;
206
206
  const before = result.substring(0, exprStart);
207
207
  const after = result.substring(outer.end + 1);
208
208
  result = before + replacement + after;
@@ -220,11 +220,60 @@ function transform(code) {
220
220
  const block = parseBlock(result, blockStart);
221
221
  if (!block) break;
222
222
  const content = result.substring(block.start + 1, block.end);
223
- const replacement = `{${list}.map(${item} => (<Fragment>${content}</Fragment>))}`;
223
+ const replacement = `{(() => ${list}.map(${item} => (<Fragment>${content}</Fragment>)))}`;
224
224
  const before = result.substring(0, exprStart);
225
225
  const after = result.substring(block.end + 1);
226
226
  result = before + replacement + after;
227
227
  }
228
+ while (true) {
229
+ const match = result.match(/\{\s*switch\s*\(/);
230
+ if (!match) break;
231
+ const exprStart = match.index;
232
+ const outer = parseBlock(result, exprStart);
233
+ if (!outer) break;
234
+ let i = consumeWhitespace(result, exprStart + 1);
235
+ const head = result.slice(i);
236
+ const mm = head.match(/^switch\s*\((.*?)\)\s*\{/);
237
+ if (!mm) break;
238
+ const cond = mm[1];
239
+ const blockStart = i + mm[0].length - 1;
240
+ const block = parseBlock(result, blockStart);
241
+ if (!block) break;
242
+ const content = result.substring(block.start + 1, block.end);
243
+ const transformedContent = content.replace(/(case\s+.*?:|default:)([\s\S]*?)(?=case\s+.*?:|default:|$)/g, (m, label, body) => {
244
+ const trimmedBody = body.trim();
245
+ if (!trimmedBody) return m;
246
+ if (trimmedBody.startsWith("return ")) return m;
247
+ return `${label} return (<Fragment>${body}</Fragment>);`;
248
+ });
249
+ const replacement = `{(() => { __ROUND_SWITCH__(${cond}) { ${transformedContent} } })}`;
250
+ const before = result.substring(0, exprStart);
251
+ const after = result.substring(outer.end + 1);
252
+ result = before + replacement + after;
253
+ }
254
+ while (true) {
255
+ const match = result.match(/(^|[\n\r])\s*switch\s*\(/m);
256
+ if (!match) break;
257
+ const switchStart = match.index + match[0].lastIndexOf("switch");
258
+ const head = result.slice(switchStart);
259
+ const mm = head.match(/^switch\s*\((.*?)\)\s*\{/);
260
+ if (!mm) break;
261
+ const cond = mm[1];
262
+ const blockStart = switchStart + mm[0].length - 1;
263
+ const block = parseBlock(result, blockStart);
264
+ if (!block) break;
265
+ const content = result.substring(block.start + 1, block.end);
266
+ const transformedContent = content.replace(/(case\s+.*?:|default:)([\s\S]*?)(?=case\s+.*?:|default:|$)/g, (m, label, body) => {
267
+ const trimmedBody = body.trim();
268
+ if (!trimmedBody) return m;
269
+ if (trimmedBody.startsWith("return ")) return m;
270
+ return `${label} return (<Fragment>${body}</Fragment>);`;
271
+ });
272
+ const replacement = `{(() => { __ROUND_SWITCH__(${cond}) { ${transformedContent} } })}`;
273
+ const before = result.substring(0, switchStart);
274
+ const after = result.substring(block.end + 1);
275
+ result = before + replacement + after;
276
+ }
228
277
  }
229
278
  function findJsxTagEnd(str, startIndex) {
230
279
  let inSingle = false;
@@ -352,7 +401,7 @@ function transform(code) {
352
401
  result = transformSuspenseBlocks(result);
353
402
  result = transformProviderBlocks(result);
354
403
  result = result.replace(/\{\s*([A-Za-z_$][\w$]*)\s*\(\s*\)\s*\}/g, "{() => $1()}").replace(/=\{\s*([A-Za-z_$][\w$]*)\s*\(\s*\)\s*\}/g, "={() => $1()}");
355
- return result;
404
+ return result.replace(/__ROUND_SWITCH__/g, "switch");
356
405
  }
357
406
  function normalizePath(p) {
358
407
  return p.replaceAll("\\", "/");