@sigil-dev/compiler 0.9.10 → 0.9.12

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.
@@ -0,0 +1,45 @@
1
+ import { afterAll, beforeAll, expect, test } from "bun:test";
2
+ import { mkdir, rm, writeFile } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { sigil } from "../src/bun-plugin.ts";
6
+
7
+ const dir = join(tmpdir(), `sigil-bun-plugin-${Date.now()}`);
8
+
9
+ beforeAll(async () => {
10
+ await mkdir(dir, { recursive: true });
11
+ await writeFile(
12
+ join(dir, "theme.ts"),
13
+ 'export let theme = $store<"light" | "dark">("light");\nexport function toggle() { theme = theme === "light" ? "dark" : "light"; }',
14
+ );
15
+ await writeFile(
16
+ join(dir, "raw.ts"),
17
+ "export let rows = $state.raw([1, 2]);\nexport const first = () => rows[0];",
18
+ );
19
+ await writeFile(
20
+ join(dir, "label.ts"),
21
+ 'import { theme } from "./theme";\nexport const label = () => "theme: " + theme;',
22
+ );
23
+ await writeFile(
24
+ join(dir, "entry.ts"),
25
+ 'import { toggle } from "./theme";\nimport { first } from "./raw";\nimport { label } from "./label";\nconsole.log(toggle, first, label);',
26
+ );
27
+ });
28
+
29
+ afterAll(() => rm(dir, { recursive: true, force: true }));
30
+
31
+ test("plain .ts modules with any macro or a store import are compiled", async () => {
32
+ const result = await Bun.build({
33
+ entrypoints: [join(dir, "entry.ts")],
34
+ plugins: [sigil({ mode: "dom" })],
35
+ external: ["@sigil-dev/runtime"],
36
+ throw: false,
37
+ });
38
+ expect(result.success).toBe(true);
39
+ const code = await result.outputs[0]!.text();
40
+ // $store<T>(…) with a type argument, and $state.raw(…)
41
+ expect(code).not.toMatch(/\$store|\$state/);
42
+ expect(code).toContain("createRawSignal");
43
+ // label.ts has no macro, but reads an imported store
44
+ expect(code).toMatch(/readStore\d*\(theme\)/);
45
+ });
@@ -172,8 +172,9 @@ describe("Hydration", () => {
172
172
  // children must not be evaluated at the call site — they claim from the
173
173
  // component's own slot, which the caller cannot see
174
174
  expect(code).toMatch(/children:\s*\[\(\)\s*=>\s*\{/);
175
- // the {children} site consumes the SSR slot and hydrates against it
176
- expect(code).toContain("hydrateSlot(_el1, _el0, () => children)");
175
+ // the {children} site consumes the SSR slot and hydrates against it;
176
+ // it's a live slot because props are read through the props object
177
+ expect(code).toContain("liveSlot(_el1, _el0, () => _props.children)");
177
178
  });
178
179
 
179
180
  test("dom mode still evaluates component children eagerly", () => {
package/test/jsx.test.ts CHANGED
@@ -57,8 +57,8 @@ describe("JSX", () => {
57
57
  const code = transform(`
58
58
  const el = <div style={{ color: "red", fontSize: "16px" }} />;
59
59
  `);
60
- expect(code).toContain('.style.color = "red"');
61
- expect(code).toContain('.style.fontSize = "16px"');
60
+ expect(code).toContain('setStyleProp(_el0, "color", "red")');
61
+ expect(code).toContain('setStyleProp(_el0, "fontSize", "16px")');
62
62
  expect(code).not.toContain("[object Object]");
63
63
  });
64
64
 
@@ -68,8 +68,10 @@ describe("JSX", () => {
68
68
  const el = <div style={{ fontSize: size + "px", color: "red" }} />;
69
69
  `);
70
70
  expect(code).toContain("createEffect");
71
- expect(code).toContain(".style.fontSize");
72
- expect(code).toContain('.style.color = "red"');
71
+ expect(code).toMatch(
72
+ /createEffect\(\(\) => \{\s*setStyleProp\(_el0, "fontSize"/,
73
+ );
74
+ expect(code).toContain('setStyleProp(_el0, "color", "red")');
73
75
  });
74
76
  });
75
77
 
@@ -156,6 +158,26 @@ describe("JSX", () => {
156
158
  expect(code).toContain("text.set(e.target.value)");
157
159
  });
158
160
 
161
+ test("camelCase bind keeps the property's casing", () => {
162
+ const code = transform(`
163
+ let top = $state(0);
164
+ const el = <div bindScrollTop={top} />;
165
+ `);
166
+ expect(code).toContain(".scrollTop = top()");
167
+ expect(code).not.toContain("scrolltop");
168
+ });
169
+
170
+ test("scroll and details bindings listen for their own events", () => {
171
+ const code = transform(`
172
+ let top = $state(0);
173
+ let open = $state(false);
174
+ const a = <div bind:scrollTop={top} />;
175
+ const b = <details bind:open={open} />;
176
+ `);
177
+ expect(code).toContain('"scroll"');
178
+ expect(code).toContain('"toggle"');
179
+ });
180
+
159
181
  test("bindChecked compiles to change event", () => {
160
182
  const code = transform(`
161
183
  let checked = $state(false);