@sigil-dev/runtime 0.7.6 → 0.8.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.
Files changed (3) hide show
  1. package/index.test.ts +79 -16
  2. package/index.ts +637 -618
  3. package/package.json +1 -1
package/index.test.ts CHANGED
@@ -28,11 +28,11 @@ import {
28
28
  easeOutSine,
29
29
  hydrateKeyedList,
30
30
  linear,
31
- reconcile,
32
- tick,
33
31
  ReactiveMap,
34
32
  ReactiveSet,
33
+ reconcile,
35
34
  snapshot,
35
+ tick,
36
36
  tracking,
37
37
  withEffectScope,
38
38
  } from "./index.ts";
@@ -360,9 +360,13 @@ describe("Runtime", () => {
360
360
  count();
361
361
  runs++;
362
362
  });
363
- batch(() => { count.set(1); });
363
+ batch(() => {
364
+ count.set(1);
365
+ });
364
366
  stop();
365
- batch(() => { count.set(2); });
367
+ batch(() => {
368
+ count.set(2);
369
+ });
366
370
  expect(runs).toBe(2); // initial + one update, not three
367
371
  });
368
372
 
@@ -558,9 +562,9 @@ describe("createSignal with arrays", () => {
558
562
  test("index access is reactive", () => {
559
563
  const items = createSignal([1, 2, 3]);
560
564
  let first = 0;
561
- //@ts-expect-error the assertion for that is below
562
565
  createEffect(() => {
563
- first = items()[0];
566
+ //@ts-expect-error the assertion for that is below
567
+ first = items()[0];
564
568
  });
565
569
  expect(first).toBe(1);
566
570
  batch(() => {
@@ -1239,11 +1243,14 @@ describe("A2 snapshot", () => {
1239
1243
  const s = snapshot(obj());
1240
1244
  expect(s.a.b.c).toBe(1);
1241
1245
  // s.a.b should NOT be a proxy — it's a plain object from the deep copy
1246
+ //biome-ignore lint: shut up
1242
1247
  const proxyTargetCheck = (val: object) =>
1243
- (typeof val === "object" && val !== null) &&
1248
+ typeof val === "object" &&
1249
+ val !== null &&
1244
1250
  !Object.getPrototypeOf(val)?.constructor?.name?.includes("Map");
1245
1251
  // Verify no nested proxy: accessing s.a.b.c should not trigger tracking
1246
- let tracked = false;
1252
+ let tracked = false;
1253
+ //biome-ignore lint: shut up
1247
1254
  const prev = (globalThis as any).__sigil_tracking_test;
1248
1255
  (globalThis as any).__sigil_tracking_test = () => (tracked = true);
1249
1256
  const raw = s.a.b;
@@ -1288,7 +1295,10 @@ describe("A4 createInspectEffect", () => {
1288
1295
  test("accepts custom callback", () => {
1289
1296
  const count = createSignal(0);
1290
1297
  const logged: unknown[][] = [];
1291
- createInspectEffect(() => [count()], (vals) => logged.push(vals));
1298
+ createInspectEffect(
1299
+ () => [count()],
1300
+ (vals) => logged.push(vals),
1301
+ );
1292
1302
  expect(logged.length).toBe(1);
1293
1303
  expect(logged[0]).toEqual([0]);
1294
1304
  });
@@ -1369,7 +1379,8 @@ describe("A7 ReactiveMap", () => {
1369
1379
  map.set("a", 1);
1370
1380
  let count = 0;
1371
1381
  createEffect(() => {
1372
- count = 0;
1382
+ count = 0;
1383
+ //biome-ignore lint: shut up
1373
1384
  map.forEach(() => count++);
1374
1385
  });
1375
1386
  expect(count).toBe(1);
@@ -1485,7 +1496,8 @@ describe("A7 ReactiveSet", () => {
1485
1496
  set.add("a");
1486
1497
  let count = 0;
1487
1498
  createEffect(() => {
1488
- count = 0;
1499
+ count = 0;
1500
+ //biome-ignore lint: shut up
1489
1501
  set.forEach(() => count++);
1490
1502
  });
1491
1503
  expect(count).toBe(1);
@@ -1516,11 +1528,21 @@ describe("A8 easing functions", () => {
1516
1528
 
1517
1529
  test("all easing functions return 0 at t=0 and 1 at t=1", () => {
1518
1530
  const fns = [
1519
- easeInQuad, easeOutQuad, easeInOutQuad,
1520
- easeInCubic, easeOutCubic, easeInOutCubic,
1521
- easeInQuart, easeOutQuart, easeInOutQuart,
1522
- easeInQuint, easeOutQuint, easeInOutQuint,
1523
- easeInSine, easeOutSine, easeInOutSine,
1531
+ easeInQuad,
1532
+ easeOutQuad,
1533
+ easeInOutQuad,
1534
+ easeInCubic,
1535
+ easeOutCubic,
1536
+ easeInOutCubic,
1537
+ easeInQuart,
1538
+ easeOutQuart,
1539
+ easeInOutQuart,
1540
+ easeInQuint,
1541
+ easeOutQuint,
1542
+ easeInOutQuint,
1543
+ easeInSine,
1544
+ easeOutSine,
1545
+ easeInOutSine,
1524
1546
  ];
1525
1547
  for (const fn of fns) {
1526
1548
  expect(fn(0)).toBeCloseTo(0, 10);
@@ -1551,3 +1573,44 @@ describe("A9 createProfilerEffect", () => {
1551
1573
  expect(seen).toBe(5);
1552
1574
  });
1553
1575
  });
1576
+
1577
+ describe("Array reactivity", () => {
1578
+ test("push on $state array triggers reactivity", async () => {
1579
+ const items = createSignal([] as string[]);
1580
+ let count = 0;
1581
+ createEffect(() => {
1582
+ items(); // now auto-tracks length
1583
+ count++;
1584
+ });
1585
+ await tick();
1586
+ expect(count).toBe(1); // initial run
1587
+ items().push("a");
1588
+ await tick();
1589
+ expect(count).toBe(2); // re-ran after push
1590
+ expect(items().length).toBe(1);
1591
+ });
1592
+
1593
+ test("pop on $state array triggers reactivity", async () => {
1594
+ const items = createSignal(["a", "b"] as string[]);
1595
+ let len = 0;
1596
+ createEffect(() => {
1597
+ len = items().length; // reads length, subscribes
1598
+ });
1599
+ await tick();
1600
+ expect(len).toBe(2);
1601
+ items().pop();
1602
+ await tick();
1603
+ expect(len).toBe(1);
1604
+ });
1605
+
1606
+ test("splice on $state array triggers reactivity", async () => {
1607
+ const items = createSignal(["a", "b", "c"] as string[]);
1608
+ let len = 0;
1609
+ createEffect(() => { len = items().length; });
1610
+ await tick();
1611
+ expect(len).toBe(3);
1612
+ items().splice(1, 1);
1613
+ await tick();
1614
+ expect(len).toBe(2);
1615
+ });
1616
+ })