@sky.ui/reactivity 0.0.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.
package/dist/index.js ADDED
@@ -0,0 +1,2671 @@
1
+ import * as acorn from 'acorn';
2
+
3
+ // src/reactivity/tracking.ts
4
+ var targetMap = /* @__PURE__ */ new WeakMap();
5
+ var runnerDeps = /* @__PURE__ */ new WeakMap();
6
+ var activeEffect = null;
7
+ var effectStack = [];
8
+ var ITERATE_KEY = /* @__PURE__ */ Symbol("iterate");
9
+ function enterEffectScope(runner) {
10
+ effectStack.push(runner);
11
+ activeEffect = runner;
12
+ }
13
+ function leaveEffectScope() {
14
+ effectStack.pop();
15
+ activeEffect = effectStack[effectStack.length - 1] ?? null;
16
+ }
17
+ function cleanupRunnerDeps(runner) {
18
+ const links = runnerDeps.get(runner);
19
+ if (!links) return;
20
+ for (const { target, key } of links) {
21
+ targetMap.get(target)?.get(key)?.delete(runner);
22
+ }
23
+ links.length = 0;
24
+ }
25
+ function stopRunner(runner) {
26
+ runner.stopped = true;
27
+ runner.paused = false;
28
+ cleanupRunnerDeps(runner);
29
+ runnerDeps.delete(runner);
30
+ }
31
+ function track(target, key) {
32
+ if (!activeEffect || activeEffect.stopped || activeEffect.paused) return;
33
+ let depsMap = targetMap.get(target);
34
+ if (!depsMap) targetMap.set(target, depsMap = /* @__PURE__ */ new Map());
35
+ let dep = depsMap.get(key);
36
+ if (!dep) depsMap.set(key, dep = /* @__PURE__ */ new Set());
37
+ if (!dep.has(activeEffect)) {
38
+ dep.add(activeEffect);
39
+ let links = runnerDeps.get(activeEffect);
40
+ if (!links) runnerDeps.set(activeEffect, links = []);
41
+ links.push({ target, key });
42
+ }
43
+ }
44
+ function trigger(target, key) {
45
+ const depsMap = targetMap.get(target);
46
+ if (!depsMap) return;
47
+ const dep = depsMap.get(key);
48
+ if (!dep) return;
49
+ dep.forEach((e) => {
50
+ if (!e.stopped && !e.paused) e.scheduler(e);
51
+ });
52
+ }
53
+
54
+ // src/reactivity/scheduler.ts
55
+ var jobQueue = /* @__PURE__ */ new Set();
56
+ var nextTickQueue = /* @__PURE__ */ new Set();
57
+ var flushing = false;
58
+ var flushPromise = null;
59
+ function flushJobs() {
60
+ jobQueue.forEach((j) => j());
61
+ jobQueue.clear();
62
+ flushing = false;
63
+ nextTickQueue.forEach((fn) => fn());
64
+ nextTickQueue.clear();
65
+ flushPromise = null;
66
+ }
67
+ function scheduleFlush() {
68
+ if (flushing) return;
69
+ flushing = true;
70
+ flushPromise ??= Promise.resolve().then(flushJobs);
71
+ }
72
+ function queueJob(job) {
73
+ jobQueue.add(job);
74
+ scheduleFlush();
75
+ }
76
+ function queueNextTick(fn) {
77
+ nextTickQueue.add(fn);
78
+ scheduleFlush();
79
+ }
80
+ function flushSync(fn) {
81
+ fn();
82
+ if (flushing || jobQueue.size > 0) {
83
+ flushJobs();
84
+ } else {
85
+ nextTickQueue.forEach((f) => f());
86
+ nextTickQueue.clear();
87
+ }
88
+ }
89
+
90
+ // src/reactivity/effect-scope.ts
91
+ var EffectScope = class {
92
+ constructor(detached = false) {
93
+ this.detached = detached;
94
+ }
95
+ detached;
96
+ active = true;
97
+ effects = [];
98
+ disposers = [];
99
+ run(fn) {
100
+ if (!this.active) return fn();
101
+ const prev = activeScope;
102
+ activeScope = this;
103
+ try {
104
+ return fn();
105
+ } finally {
106
+ activeScope = prev;
107
+ }
108
+ }
109
+ register(runner) {
110
+ if (!this.active) {
111
+ runner.stop();
112
+ return;
113
+ }
114
+ this.effects.push(runner);
115
+ }
116
+ registerDispose(fn) {
117
+ if (!this.active) {
118
+ fn();
119
+ return;
120
+ }
121
+ this.disposers.push(fn);
122
+ }
123
+ stop() {
124
+ if (!this.active) return;
125
+ this.active = false;
126
+ for (const d of this.disposers) d();
127
+ this.disposers.length = 0;
128
+ for (const e of this.effects) e.stop();
129
+ this.effects.length = 0;
130
+ }
131
+ };
132
+ var activeScope = null;
133
+ function effectScope(detached = false) {
134
+ return new EffectScope(detached);
135
+ }
136
+ function getCurrentScope() {
137
+ return activeScope;
138
+ }
139
+ function onScopeDispose(fn) {
140
+ activeScope?.registerDispose(fn);
141
+ }
142
+
143
+ // src/reactivity/effect.ts
144
+ function effect(fn, opts = {}) {
145
+ let cleanupFn;
146
+ const runner = (() => {
147
+ if (runner.stopped || runner.paused) return;
148
+ if (cleanupFn) {
149
+ cleanupFn();
150
+ cleanupFn = void 0;
151
+ }
152
+ cleanupRunnerDeps(runner);
153
+ try {
154
+ enterEffectScope(runner);
155
+ return fn();
156
+ } finally {
157
+ leaveEffectScope();
158
+ }
159
+ });
160
+ runner.stopped = false;
161
+ runner.paused = false;
162
+ runner.stop = () => stopRunner(runner);
163
+ runner.pause = () => {
164
+ runner.paused = true;
165
+ };
166
+ runner.resume = () => {
167
+ if (runner.stopped) return;
168
+ runner.paused = false;
169
+ runner();
170
+ };
171
+ runner.scheduler = opts.scheduler ?? queueJob;
172
+ if (opts.onCleanup) {
173
+ cleanupFn = opts.onCleanup;
174
+ }
175
+ getCurrentScope()?.register(runner);
176
+ if (!opts.lazy) runner();
177
+ return runner;
178
+ }
179
+ var watchEffect = effect;
180
+
181
+ // src/reactivity/ref-flags.ts
182
+ var REF_FLAG = "__isRef";
183
+ function isRef(v) {
184
+ return !!(v && typeof v === "object" && v[REF_FLAG] === true);
185
+ }
186
+ function unref(v) {
187
+ return isRef(v) ? v.value : v;
188
+ }
189
+
190
+ // src/reactivity/proxy-state.ts
191
+ function isPlainObject(o) {
192
+ if (!o || typeof o !== "object") return false;
193
+ const p = Object.getPrototypeOf(o);
194
+ return p === Object.prototype || p === null;
195
+ }
196
+ function shouldWrap(v) {
197
+ return Array.isArray(v) || isPlainObject(v);
198
+ }
199
+ var proxyCache = /* @__PURE__ */ new WeakMap();
200
+ var proxyToRaw = /* @__PURE__ */ new WeakMap();
201
+ var markRawSet = /* @__PURE__ */ new WeakSet();
202
+ var readonlyProxyCache = /* @__PURE__ */ new WeakMap();
203
+ var READONLY_FLAG = "__isReadonly";
204
+
205
+ // src/reactivity/reactive.ts
206
+ function reactive(obj) {
207
+ if (!obj || typeof obj !== "object") return obj;
208
+ if (obj.__isReactive) return obj;
209
+ if (markRawSet.has(obj)) return obj;
210
+ const cached = proxyCache.get(obj);
211
+ if (cached) return cached;
212
+ if (Array.isArray(obj)) {
213
+ const arrayMethods = [
214
+ "push",
215
+ "pop",
216
+ "shift",
217
+ "unshift",
218
+ "splice",
219
+ "sort",
220
+ "reverse"
221
+ ];
222
+ const p2 = new Proxy(obj, {
223
+ get(target, key, receiver) {
224
+ if (key === "__isReactive") return true;
225
+ if (typeof key === "string" && arrayMethods.includes(key)) {
226
+ return function(...args) {
227
+ const oldLength = target.length;
228
+ const mutator = key;
229
+ const proto = Array.prototype;
230
+ const fn = proto[mutator];
231
+ if (!fn) return void 0;
232
+ const result = fn.apply(target, args);
233
+ if (target.length !== oldLength) trigger(target, "length");
234
+ if (key === "push" || key === "unshift" || key === "splice") {
235
+ for (let i = 0; i < target.length; i++) trigger(target, i + "");
236
+ }
237
+ return result;
238
+ };
239
+ }
240
+ const value = Reflect.get(target, key, receiver);
241
+ track(target, key);
242
+ return shouldWrap(value) ? reactive(value) : value;
243
+ },
244
+ set(target, key, value, receiver) {
245
+ const old = Reflect.get(target, key);
246
+ const result = Reflect.set(target, key, value, receiver);
247
+ if (old !== value) {
248
+ trigger(target, key);
249
+ if (typeof key === "string" && key !== "" && !Number.isNaN(Number(key))) {
250
+ trigger(target, key);
251
+ }
252
+ }
253
+ return result;
254
+ },
255
+ has(target, key) {
256
+ track(target, key);
257
+ return Reflect.has(target, key);
258
+ },
259
+ deleteProperty(target, key) {
260
+ const hadKey = Object.prototype.hasOwnProperty.call(target, key);
261
+ const result = Reflect.deleteProperty(target, key);
262
+ if (hadKey) {
263
+ trigger(target, key);
264
+ trigger(target, "length");
265
+ }
266
+ return result;
267
+ }
268
+ });
269
+ proxyCache.set(obj, p2);
270
+ proxyToRaw.set(p2, obj);
271
+ return p2;
272
+ }
273
+ const p = new Proxy(obj, {
274
+ get(t, k, r) {
275
+ if (k === "__isReactive") return true;
276
+ const v = Reflect.get(t, k, r);
277
+ track(t, k);
278
+ if (isRef(v)) {
279
+ const u = v.value;
280
+ return shouldWrap(u) ? reactive(u) : u;
281
+ }
282
+ return shouldWrap(v) ? reactive(v) : v;
283
+ },
284
+ set(t, k, v, r) {
285
+ const old = Reflect.get(t, k);
286
+ const hadKey = Object.prototype.hasOwnProperty.call(t, k);
287
+ const res = Reflect.set(t, k, v, r);
288
+ if (old !== v) {
289
+ trigger(t, k);
290
+ if (!hadKey) trigger(t, ITERATE_KEY);
291
+ }
292
+ return res;
293
+ },
294
+ has(t, k) {
295
+ track(t, k);
296
+ return Reflect.has(t, k);
297
+ },
298
+ deleteProperty(t, k) {
299
+ const hadKey = Object.prototype.hasOwnProperty.call(t, k);
300
+ const res = Reflect.deleteProperty(t, k);
301
+ if (hadKey) {
302
+ trigger(t, k);
303
+ trigger(t, ITERATE_KEY);
304
+ }
305
+ return res;
306
+ },
307
+ ownKeys(t) {
308
+ track(t, ITERATE_KEY);
309
+ return Reflect.ownKeys(t);
310
+ }
311
+ });
312
+ proxyCache.set(obj, p);
313
+ proxyToRaw.set(p, obj);
314
+ return p;
315
+ }
316
+
317
+ // src/reactivity/readonly.ts
318
+ function readonly(obj) {
319
+ if (!obj || typeof obj !== "object") return obj;
320
+ if (obj[READONLY_FLAG]) return obj;
321
+ if (markRawSet.has(obj)) return obj;
322
+ const cached = readonlyProxyCache.get(obj);
323
+ if (cached) return cached;
324
+ const p = new Proxy(obj, {
325
+ get(t, k, r) {
326
+ if (k === "__isReactive" || k === READONLY_FLAG) return true;
327
+ const v = Reflect.get(t, k, r);
328
+ track(t, k);
329
+ if (isRef(v)) {
330
+ const u = v.value;
331
+ return shouldWrap(u) ? readonly(u) : u;
332
+ }
333
+ return shouldWrap(v) ? readonly(v) : v;
334
+ },
335
+ set() {
336
+ return true;
337
+ },
338
+ has(t, k) {
339
+ track(t, k);
340
+ return Reflect.has(t, k);
341
+ },
342
+ deleteProperty() {
343
+ return true;
344
+ },
345
+ ownKeys(t) {
346
+ track(t, ITERATE_KEY);
347
+ return Reflect.ownKeys(t);
348
+ }
349
+ });
350
+ readonlyProxyCache.set(obj, p);
351
+ proxyToRaw.set(p, obj);
352
+ return p;
353
+ }
354
+
355
+ // src/reactivity/shallow-reactive.ts
356
+ var shallowProxyCache = /* @__PURE__ */ new WeakMap();
357
+ function shallowReactive(obj) {
358
+ if (!obj || typeof obj !== "object") return obj;
359
+ if (obj.__isReactive) return obj;
360
+ if (markRawSet.has(obj)) return obj;
361
+ const cached = shallowProxyCache.get(obj);
362
+ if (cached) return cached;
363
+ const p = new Proxy(obj, {
364
+ get(t, k, r) {
365
+ if (k === "__isReactive") return true;
366
+ const v = Reflect.get(t, k, r);
367
+ track(t, k);
368
+ if (isRef(v)) return v.value;
369
+ return v;
370
+ },
371
+ set(t, k, v, r) {
372
+ const old = Reflect.get(t, k);
373
+ const hadKey = Object.prototype.hasOwnProperty.call(t, k);
374
+ const res = Reflect.set(t, k, v, r);
375
+ if (old !== v) {
376
+ trigger(t, k);
377
+ if (!hadKey) trigger(t, ITERATE_KEY);
378
+ }
379
+ return res;
380
+ },
381
+ has(t, k) {
382
+ track(t, k);
383
+ return Reflect.has(t, k);
384
+ },
385
+ deleteProperty(t, k) {
386
+ const hadKey = Object.prototype.hasOwnProperty.call(t, k);
387
+ const res = Reflect.deleteProperty(t, k);
388
+ if (hadKey) {
389
+ trigger(t, k);
390
+ trigger(t, ITERATE_KEY);
391
+ }
392
+ return res;
393
+ },
394
+ ownKeys(t) {
395
+ track(t, ITERATE_KEY);
396
+ return Reflect.ownKeys(t);
397
+ }
398
+ });
399
+ shallowProxyCache.set(obj, p);
400
+ proxyToRaw.set(p, obj);
401
+ return p;
402
+ }
403
+
404
+ // src/reactivity/shallow-readonly.ts
405
+ var shallowReadonlyCache = /* @__PURE__ */ new WeakMap();
406
+ function shallowReadonly(obj) {
407
+ if (!obj || typeof obj !== "object") return obj;
408
+ if (markRawSet.has(obj)) return obj;
409
+ const cached = shallowReadonlyCache.get(obj);
410
+ if (cached) return cached;
411
+ const p = new Proxy(obj, {
412
+ get(t, k, r) {
413
+ if (k === "__isReactive" || k === READONLY_FLAG) return true;
414
+ const v = Reflect.get(t, k, r);
415
+ track(t, k);
416
+ if (isRef(v)) return v.value;
417
+ return v;
418
+ },
419
+ set() {
420
+ return true;
421
+ },
422
+ has(t, k) {
423
+ track(t, k);
424
+ return Reflect.has(t, k);
425
+ },
426
+ deleteProperty() {
427
+ return true;
428
+ },
429
+ ownKeys(t) {
430
+ track(t, ITERATE_KEY);
431
+ return Reflect.ownKeys(t);
432
+ }
433
+ });
434
+ shallowReadonlyCache.set(obj, p);
435
+ proxyToRaw.set(p, obj);
436
+ return p;
437
+ }
438
+
439
+ // src/reactivity/proxy-api.ts
440
+ function toRaw(proxy) {
441
+ return proxyToRaw.get(proxy) ?? proxy;
442
+ }
443
+ function markRaw(obj) {
444
+ if (obj != null && typeof obj === "object") markRawSet.add(obj);
445
+ return obj;
446
+ }
447
+ function isReactive(obj) {
448
+ return !!(obj && typeof obj === "object" && obj.__isReactive === true);
449
+ }
450
+ function isReadonly(obj) {
451
+ return !!(obj && typeof obj === "object" && obj[READONLY_FLAG] === true);
452
+ }
453
+
454
+ // src/types.ts
455
+ var SHALLOW_REF_TARGET = /* @__PURE__ */ Symbol("shallowRefTarget");
456
+
457
+ // src/reactivity/ref.ts
458
+ function ref(v) {
459
+ const r = reactive({ value: v });
460
+ Object.defineProperty(r, REF_FLAG, { value: true });
461
+ return r;
462
+ }
463
+ function shallowRef(v) {
464
+ const inner = { value: v };
465
+ const shallow = {
466
+ get value() {
467
+ track(inner, "value");
468
+ return inner.value;
469
+ },
470
+ set value(val) {
471
+ inner.value = val;
472
+ trigger(inner, "value");
473
+ }
474
+ };
475
+ Object.defineProperty(shallow, REF_FLAG, { value: true });
476
+ Object.defineProperty(shallow, SHALLOW_REF_TARGET, { value: inner });
477
+ return shallow;
478
+ }
479
+ function triggerRef(r) {
480
+ const inner = r && isRef(r) ? r[SHALLOW_REF_TARGET] : void 0;
481
+ if (inner) trigger(inner, "value");
482
+ }
483
+ function customRef(factory) {
484
+ const inner = { value: void 0 };
485
+ const trackDep = () => track(inner, "value");
486
+ const triggerDep = () => trigger(inner, "value");
487
+ const { get, set } = factory(trackDep, triggerDep);
488
+ const r = {
489
+ get value() {
490
+ trackDep();
491
+ return get();
492
+ },
493
+ set value(v) {
494
+ set(v);
495
+ triggerDep();
496
+ }
497
+ };
498
+ Object.defineProperty(r, REF_FLAG, { value: true });
499
+ return r;
500
+ }
501
+
502
+ // src/reactivity/to-ref.ts
503
+ function toRef(object, key) {
504
+ const r = {
505
+ get value() {
506
+ const v = object[key];
507
+ return isRef(v) ? v.value : v;
508
+ },
509
+ set value(val) {
510
+ const cur = object[key];
511
+ if (isRef(cur)) cur.value = val;
512
+ else object[key] = val;
513
+ }
514
+ };
515
+ Object.defineProperty(r, REF_FLAG, { value: true });
516
+ return r;
517
+ }
518
+ function toRefs(object) {
519
+ const ret = {};
520
+ for (const key of Object.keys(object)) {
521
+ ret[key] = toRef(object, key);
522
+ }
523
+ return ret;
524
+ }
525
+
526
+ // src/reactivity/computed.ts
527
+ function computed(getterOrOptions) {
528
+ const onlyGetter = typeof getterOrOptions === "function";
529
+ const getter = onlyGetter ? getterOrOptions : getterOrOptions.get;
530
+ const setter = onlyGetter ? void 0 : getterOrOptions.set;
531
+ const r = ref(void 0);
532
+ effect(() => {
533
+ r.value = getter();
534
+ });
535
+ if (setter !== void 0) {
536
+ return {
537
+ get value() {
538
+ return r.value;
539
+ },
540
+ set value(v) {
541
+ setter(v);
542
+ },
543
+ [REF_FLAG]: true
544
+ };
545
+ }
546
+ return r;
547
+ }
548
+
549
+ // src/reactivity/watch.ts
550
+ function watch(src, cb, opts = {}) {
551
+ const { immediate = false, deep = false, flush = "post" } = opts;
552
+ const isMulti = Array.isArray(src);
553
+ const getter = isMulti ? () => src.map((s) => typeof s === "function" ? s() : unref(s)) : typeof src === "function" ? src : () => unref(src);
554
+ const traverse = (v, seen = /* @__PURE__ */ new Set()) => {
555
+ v = unref(v);
556
+ if (!v || typeof v !== "object" || seen.has(v)) return v;
557
+ seen.add(v);
558
+ if (Array.isArray(v)) {
559
+ v.length;
560
+ for (let i = 0; i < v.length; i++) traverse(v[i], seen);
561
+ } else {
562
+ const record = v;
563
+ for (const k in record) traverse(record[k], seen);
564
+ }
565
+ return v;
566
+ };
567
+ let old;
568
+ let cleanup2;
569
+ const run = () => {
570
+ if (cleanup2) {
571
+ cleanup2();
572
+ cleanup2 = void 0;
573
+ }
574
+ const val = getter();
575
+ if (deep) traverse(val);
576
+ const prev = old;
577
+ const shouldCall = prev !== void 0 || immediate;
578
+ old = val;
579
+ if (shouldCall) {
580
+ const onCleanup = (fn) => {
581
+ cleanup2 = fn;
582
+ };
583
+ cb(val, prev, onCleanup);
584
+ }
585
+ };
586
+ const scheduler = flush === "sync" ? (runFn) => runFn() : (runFn) => queueJob(runFn);
587
+ const runner = effect(run, { lazy: !immediate, scheduler });
588
+ return () => runner.stop();
589
+ }
590
+
591
+ // src/reactivity/next-tick.ts
592
+ var nextTick = (fn) => {
593
+ if (fn) {
594
+ return new Promise((resolve) => {
595
+ queueNextTick(() => {
596
+ fn();
597
+ resolve();
598
+ });
599
+ });
600
+ }
601
+ return new Promise((resolve) => {
602
+ queueNextTick(() => resolve());
603
+ });
604
+ };
605
+ var exprCache = /* @__PURE__ */ new Map();
606
+ var stmtCache = /* @__PURE__ */ new Map();
607
+ function stripSemi(s) {
608
+ return String(s || "").trim().replace(/;+\s*$/g, "");
609
+ }
610
+ function parseExpr(expr) {
611
+ const src = stripSemi(expr) || "undefined";
612
+ let ast = exprCache.get(src);
613
+ if (!ast) {
614
+ try {
615
+ const program = acorn.parse(`(${src})`, {
616
+ ecmaVersion: "latest",
617
+ sourceType: "script"
618
+ });
619
+ const first = program.body[0];
620
+ if (first?.type !== "ExpressionStatement") {
621
+ throw new SyntaxError(`[Sky parseExpr] Expected expression, got ${first?.type ?? "empty"}`);
622
+ }
623
+ ast = first.expression;
624
+ exprCache.set(src, ast);
625
+ } catch (e) {
626
+ const msg = e instanceof Error ? e.message : String(e);
627
+ throw new SyntaxError(`[Sky parseExpr] ${msg}
628
+ SRC: ${src}`);
629
+ }
630
+ }
631
+ return ast;
632
+ }
633
+ function parseStmt(code) {
634
+ code = String(code || "").trim();
635
+ if (!stmtCache.has(code)) {
636
+ const program = acorn.parse(code, {
637
+ ecmaVersion: "latest",
638
+ sourceType: "script",
639
+ allowAwaitOutsideFunction: true,
640
+ allowReturnOutsideFunction: true
641
+ });
642
+ stmtCache.set(code, program);
643
+ }
644
+ const cached = stmtCache.get(code);
645
+ if (!cached) throw new SyntaxError("[Sky parseStmt] failed to parse");
646
+ return cached;
647
+ }
648
+ function compileExpr(expr) {
649
+ return parseExpr(expr);
650
+ }
651
+ function compileStmt(code) {
652
+ return parseStmt(code);
653
+ }
654
+ function clearAstCaches() {
655
+ exprCache.clear();
656
+ stmtCache.clear();
657
+ }
658
+
659
+ // src/ast/constants.ts
660
+ var SAFE_GLOBALS = Object.freeze({
661
+ Math,
662
+ Number,
663
+ String,
664
+ Boolean,
665
+ Array,
666
+ Object,
667
+ JSON,
668
+ Date,
669
+ RegExp,
670
+ parseInt,
671
+ parseFloat,
672
+ isNaN,
673
+ isFinite,
674
+ console
675
+ // optional
676
+ });
677
+ var BLOCKED_PROPS = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor"]);
678
+ var BLOCKED_IDENTIFIERS = /* @__PURE__ */ new Set([
679
+ "window",
680
+ "self",
681
+ "document",
682
+ "globalThis",
683
+ "Function",
684
+ "eval",
685
+ "constructor",
686
+ "__proto__",
687
+ "prototype",
688
+ "location",
689
+ "localStorage",
690
+ "sessionStorage",
691
+ "indexedDB",
692
+ "navigator",
693
+ "fetch",
694
+ "XMLHttpRequest",
695
+ "WebSocket"
696
+ ]);
697
+
698
+ // src/shared/env.ts
699
+ function getSkyDev() {
700
+ if (typeof globalThis.__SKY_DEV__ === "boolean") {
701
+ return globalThis.__SKY_DEV__;
702
+ }
703
+ return typeof process !== "undefined" && process.env.NODE_ENV === "production" ? false : true;
704
+ }
705
+ function setSkyDev(enabled) {
706
+ globalThis.__SKY_DEV__ = enabled;
707
+ }
708
+ var skyDevSnapshot = getSkyDev();
709
+
710
+ // src/shared/warn-codes.ts
711
+ var WarnCodes = {
712
+ MODEL_ARG_ON_NATIVE: "MODEL_ARG_ON_NATIVE",
713
+ MODEL_INVALID_KEY: "MODEL_INVALID_KEY",
714
+ MODEL_UNKNOWN_MODIFIER: "MODEL_UNKNOWN_MODIFIER",
715
+ MODEL_DUPLICATE: "MODEL_DUPLICATE",
716
+ FOR_KEY_RECOMMENDED: "FOR_KEY_RECOMMENDED",
717
+ FOR_INVALID_SYNTAX: "FOR_INVALID_SYNTAX",
718
+ EVENT_UNKNOWN_MODIFIER: "EVENT_UNKNOWN_MODIFIER",
719
+ HANDLER_RUNTIME: "HANDLER_RUNTIME",
720
+ AST_EVAL: "AST_EVAL",
721
+ AST_STMT: "AST_STMT",
722
+ AST_BLOCKED: "AST_BLOCKED",
723
+ MOUNT_TARGET_NOT_FOUND: "MOUNT_TARGET_NOT_FOUND",
724
+ SSR_ROOT_NOT_FOUND: "SSR_ROOT_NOT_FOUND",
725
+ SKY_HTML_UNSAFE: "SKY_HTML_UNSAFE"
726
+ };
727
+ var messages = {
728
+ [WarnCodes.MODEL_ARG_ON_NATIVE]: 'sky-model:{arg} is for custom elements only. On <{tag}> use sky-model="{key}" without an argument.',
729
+ [WarnCodes.MODEL_INVALID_KEY]: 'Invalid sky-model value "{value}". Expected a single identifier (e.g. sky-model="count").',
730
+ [WarnCodes.MODEL_UNKNOWN_MODIFIER]: 'Unknown sky-model modifier(s) "{mods}". Supported: .lazy, .number, .trim.',
731
+ [WarnCodes.MODEL_DUPLICATE]: "Multiple sky-model bindings on the same element. Only one is applied.",
732
+ [WarnCodes.FOR_KEY_RECOMMENDED]: 'sky-for without sky-key may recreate DOM nodes on list updates. Add sky-key="item.id" (or a stable key).',
733
+ [WarnCodes.FOR_INVALID_SYNTAX]: 'Invalid sky-for="{expr}". Use `item in items` or `(item, index) in items`.',
734
+ [WarnCodes.EVENT_UNKNOWN_MODIFIER]: 'Unknown event modifier "{mod}" on @{event}. Ignored.',
735
+ [WarnCodes.HANDLER_RUNTIME]: "Unhandled error in event handler{label}.",
736
+ [WarnCodes.AST_EVAL]: "Expression evaluation failed{label}.",
737
+ [WarnCodes.AST_STMT]: "Statement execution failed{label}.",
738
+ [WarnCodes.AST_BLOCKED]: "{detail}",
739
+ [WarnCodes.MOUNT_TARGET_NOT_FOUND]: 'Failed to mount: target "{target}" was not found.',
740
+ [WarnCodes.SSR_ROOT_NOT_FOUND]: 'SSR root "{root}" was not found in markup.',
741
+ [WarnCodes.SKY_HTML_UNSAFE]: "sky-html sets innerHTML from an expression. Only bind trusted content to avoid XSS."
742
+ };
743
+ function getWarnMessage(code, args = {}) {
744
+ let msg = messages[code] ?? code;
745
+ for (const [k, v] of Object.entries(args)) {
746
+ msg = msg.replaceAll(`{${k}}`, String(v));
747
+ }
748
+ return msg.replace(/\{(\w+)\}/g, "");
749
+ }
750
+
751
+ // src/shared/warn.ts
752
+ var warnedKeys = /* @__PURE__ */ new Set();
753
+ var elementIds = /* @__PURE__ */ new WeakMap();
754
+ var nextElementId = 0;
755
+ var customHandler = null;
756
+ function setWarnHandler(handler) {
757
+ customHandler = handler;
758
+ }
759
+ function elementInstanceKey(el) {
760
+ if (!el) return "";
761
+ let id = elementIds.get(el);
762
+ if (id === void 0) {
763
+ id = ++nextElementId;
764
+ elementIds.set(el, id);
765
+ }
766
+ return String(id);
767
+ }
768
+ function warnKey(code, context) {
769
+ return `${code}:${elementInstanceKey(context?.element)}:${context?.label ?? ""}`;
770
+ }
771
+ function formatElement(el) {
772
+ const tag = el.tagName.toLowerCase();
773
+ const id = el.id ? `#${el.id}` : "";
774
+ const extra = describeElement(el);
775
+ return extra ? `<${tag}${id} ${extra}>` : `<${tag}${id}>`;
776
+ }
777
+ function describeElement(el) {
778
+ const hints = [];
779
+ const skyFor = el.getAttribute("sky-for");
780
+ if (skyFor) {
781
+ hints.push(
782
+ `sky-for="${skyFor.slice(0, 48)}${skyFor.length > 48 ? "\u2026" : ""}"`
783
+ );
784
+ }
785
+ const skyIf = el.getAttribute("sky-if") ?? el.getAttribute("sky-else-if");
786
+ if (skyIf) hints.push(`sky-if="${skyIf.slice(0, 48)}"`);
787
+ return hints.join(" ");
788
+ }
789
+ function formatTrace(context) {
790
+ const lines = [];
791
+ if (context?.element) {
792
+ lines.push(` at ${formatElement(context.element)}`);
793
+ }
794
+ if (context?.label) {
795
+ lines.push(` (${context.label})`);
796
+ }
797
+ return lines.length > 0 ? "\n" + lines.join("\n") : "";
798
+ }
799
+ function emitWarn(code, message, context) {
800
+ if (!getSkyDev()) return;
801
+ const trace = formatTrace(context);
802
+ const full = `[Sky warn]: ${message}${trace}`;
803
+ if (customHandler) {
804
+ customHandler(code, message, context);
805
+ return;
806
+ }
807
+ console.warn(full);
808
+ }
809
+ function warn(code, args = {}, context) {
810
+ emitWarn(code, getWarnMessage(code, args), context);
811
+ }
812
+ function warnOnce(code, args = {}, context) {
813
+ if (!getSkyDev()) return;
814
+ const key = warnKey(code, context);
815
+ if (warnedKeys.has(key)) return;
816
+ warnedKeys.add(key);
817
+ warn(code, args, context);
818
+ }
819
+ function logError(code, err, context) {
820
+ if (!getSkyDev()) {
821
+ if (code === WarnCodes.HANDLER_RUNTIME) {
822
+ console.error(err);
823
+ }
824
+ return;
825
+ }
826
+ const labelArg = context?.label ? { label: ` (${context.label})` } : { label: "" };
827
+ const message = getWarnMessage(code, labelArg);
828
+ const trace = formatTrace(context);
829
+ if (customHandler) {
830
+ customHandler(code, `${message} ${formatErr(err)}`, context);
831
+ return;
832
+ }
833
+ console.warn(`[Sky warn]: ${message}${trace}`);
834
+ if (err != null) {
835
+ console.warn(formatErr(err));
836
+ }
837
+ }
838
+ function formatErr(err) {
839
+ if (err instanceof Error) {
840
+ return err.stack ?? err.message;
841
+ }
842
+ return String(err);
843
+ }
844
+ function resetWarned() {
845
+ warnedKeys.clear();
846
+ }
847
+
848
+ // src/ast/errors.ts
849
+ function fail(msg) {
850
+ throw new Error("[Sky] " + msg);
851
+ }
852
+ function isObjectLike(v) {
853
+ return v !== null && (typeof v === "object" || typeof v === "function");
854
+ }
855
+ function assertSafeMemberKey(key) {
856
+ if (typeof key === "string" && BLOCKED_PROPS.has(key)) {
857
+ if (getSkyDev()) {
858
+ warn(
859
+ WarnCodes.AST_BLOCKED,
860
+ {
861
+ detail: `Blocked property access: ${key}. Use a method on context instead.`
862
+ },
863
+ { label: "expression" }
864
+ );
865
+ }
866
+ fail(`Blocked property access: ${key}`);
867
+ }
868
+ }
869
+ function assertSafeIdentifier(name) {
870
+ if (BLOCKED_IDENTIFIERS.has(name)) {
871
+ if (getSkyDev()) {
872
+ warn(
873
+ WarnCodes.AST_BLOCKED,
874
+ {
875
+ detail: `Blocked identifier "${name}" in template code. Expose a safe helper from setup instead.`
876
+ },
877
+ { label: "expression" }
878
+ );
879
+ }
880
+ fail(`Blocked identifier: ${name}`);
881
+ }
882
+ }
883
+ function toKey(v) {
884
+ return typeof v === "symbol" ? String(v) : v;
885
+ }
886
+
887
+ // src/ast/scope.ts
888
+ function createScope(ctx, locals = null) {
889
+ return { ctx, locals: locals ?? /* @__PURE__ */ Object.create(null) };
890
+ }
891
+ function getVar(scope, name) {
892
+ assertSafeIdentifier(name);
893
+ if (name in scope.locals) return scope.locals[name];
894
+ if (name in scope.ctx) return scope.ctx[name];
895
+ if (name in SAFE_GLOBALS) return SAFE_GLOBALS[name];
896
+ return void 0;
897
+ }
898
+ function setVar(scope, name, value) {
899
+ assertSafeIdentifier(name);
900
+ let cur;
901
+ let where = "ctx";
902
+ if (name in scope.locals) {
903
+ cur = scope.locals[name];
904
+ where = "locals";
905
+ } else if (name in scope.ctx) {
906
+ cur = scope.ctx[name];
907
+ where = "ctx";
908
+ } else {
909
+ cur = void 0;
910
+ where = "ctx";
911
+ }
912
+ if (isRef(cur) && !isRef(value)) {
913
+ cur.value = value;
914
+ return value;
915
+ }
916
+ if (where === "locals") scope.locals[name] = value;
917
+ else scope.ctx[name] = value;
918
+ return value;
919
+ }
920
+
921
+ // src/ast/member.ts
922
+ function getMember(obj, key) {
923
+ assertSafeMemberKey(key);
924
+ if (!isObjectLike(obj)) return void 0;
925
+ return obj[key];
926
+ }
927
+ function setMember(obj, key, value) {
928
+ assertSafeMemberKey(key);
929
+ if (!isObjectLike(obj)) fail("Cannot set property on non-object");
930
+ obj[key] = value;
931
+ return value;
932
+ }
933
+ function unwrapRefForMember(obj, key) {
934
+ if (isRef(obj) && key !== "value") return obj.value;
935
+ return obj;
936
+ }
937
+
938
+ // src/ast/operators.ts
939
+ function num(v) {
940
+ return Number(v);
941
+ }
942
+ function evalBinary(op, a, b) {
943
+ switch (op) {
944
+ case "+":
945
+ return num(a) + num(b);
946
+ case "-":
947
+ return num(a) - num(b);
948
+ case "*":
949
+ return num(a) * num(b);
950
+ case "/":
951
+ return num(a) / num(b);
952
+ case "%":
953
+ return num(a) % num(b);
954
+ case "**":
955
+ return num(a) ** num(b);
956
+ case "==":
957
+ return a == b;
958
+ case "!=":
959
+ return a != b;
960
+ case "===":
961
+ return a === b;
962
+ case "!==":
963
+ return a !== b;
964
+ case "<":
965
+ return num(a) < num(b);
966
+ case "<=":
967
+ return num(a) <= num(b);
968
+ case ">":
969
+ return num(a) > num(b);
970
+ case ">=":
971
+ return num(a) >= num(b);
972
+ case "|":
973
+ return num(a) | num(b);
974
+ case "&":
975
+ return num(a) & num(b);
976
+ case "^":
977
+ return num(a) ^ num(b);
978
+ case "<<":
979
+ return num(a) << num(b);
980
+ case ">>":
981
+ return num(a) >> num(b);
982
+ case ">>>":
983
+ return num(a) >>> num(b);
984
+ case "in":
985
+ return typeof b === "object" && b !== null && String(a) in b;
986
+ case "instanceof":
987
+ return typeof b === "function" && typeof a === "object" && a !== null && a instanceof b;
988
+ default:
989
+ fail("Unsupported binary op: " + op);
990
+ }
991
+ }
992
+ function evalUnary(op, v) {
993
+ switch (op) {
994
+ case "+":
995
+ return +num(v);
996
+ case "-":
997
+ return -num(v);
998
+ case "!":
999
+ return !v;
1000
+ case "~":
1001
+ return ~num(v);
1002
+ case "typeof":
1003
+ return typeof v;
1004
+ case "void":
1005
+ return void v;
1006
+ case "delete":
1007
+ return true;
1008
+ default:
1009
+ fail("Unsupported unary op: " + op);
1010
+ }
1011
+ }
1012
+ function applyAssignment(op, leftVal, rightVal) {
1013
+ switch (op) {
1014
+ case "=":
1015
+ return rightVal;
1016
+ case "+=":
1017
+ return num(leftVal) + num(rightVal);
1018
+ case "-=":
1019
+ return num(leftVal) - num(rightVal);
1020
+ case "*=":
1021
+ return num(leftVal) * num(rightVal);
1022
+ case "/=":
1023
+ return num(leftVal) / num(rightVal);
1024
+ case "%=":
1025
+ return num(leftVal) % num(rightVal);
1026
+ case "**=":
1027
+ return num(leftVal) ** num(rightVal);
1028
+ case "|=":
1029
+ return num(leftVal) | num(rightVal);
1030
+ case "&=":
1031
+ return num(leftVal) & num(rightVal);
1032
+ case "^=":
1033
+ return num(leftVal) ^ num(rightVal);
1034
+ case "<<=":
1035
+ return num(leftVal) << num(rightVal);
1036
+ case ">>=":
1037
+ return num(leftVal) >> num(rightVal);
1038
+ case ">>>=":
1039
+ return num(leftVal) >>> num(rightVal);
1040
+ default:
1041
+ fail("Unsupported assignment op: " + op);
1042
+ }
1043
+ }
1044
+
1045
+ // src/ast/eval-expression.ts
1046
+ function resolveLValue(node, scope, meta) {
1047
+ if (node.type === "Identifier") {
1048
+ assertSafeIdentifier(node.name);
1049
+ return {
1050
+ get: () => getVar(scope, node.name),
1051
+ set: (v) => setVar(scope, node.name, v)
1052
+ };
1053
+ }
1054
+ if (node.type === "MemberExpression") {
1055
+ let obj = evalExpression(node.object, scope);
1056
+ const key = node.computed ? toKey(evalExpression(node.property, scope)) : node.property.name;
1057
+ obj = unwrapRefForMember(obj, key);
1058
+ return {
1059
+ get: () => getMember(obj, key),
1060
+ set: (v) => setMember(obj, key, v)
1061
+ };
1062
+ }
1063
+ fail("Invalid assignment target: " + node.type);
1064
+ }
1065
+ function evalExpression(node, scope, meta) {
1066
+ switch (node.type) {
1067
+ case "Literal":
1068
+ return node.value;
1069
+ case "Identifier":
1070
+ return unref(getVar(scope, node.name));
1071
+ case "ThisExpression":
1072
+ return void 0;
1073
+ case "ArrayExpression":
1074
+ return node.elements.map(
1075
+ (el) => el ? evalExpression(el, scope) : void 0
1076
+ );
1077
+ case "ObjectExpression": {
1078
+ const out = {};
1079
+ for (const p of node.properties) {
1080
+ if (p.type !== "Property")
1081
+ fail("Unsupported object property: " + p.type);
1082
+ const k = p.computed ? evalExpression(p.key, scope) : p.key.type === "Identifier" ? p.key.name : p.key.value;
1083
+ assertSafeMemberKey(k);
1084
+ out[k] = evalExpression(p.value, scope);
1085
+ }
1086
+ return out;
1087
+ }
1088
+ case "TemplateLiteral": {
1089
+ let s = "";
1090
+ for (let i = 0; i < node.quasis.length; i++) {
1091
+ s += node.quasis[i].value.cooked || "";
1092
+ if (node.expressions[i]) {
1093
+ s += String(evalExpression(node.expressions[i], scope) ?? "");
1094
+ }
1095
+ }
1096
+ return s;
1097
+ }
1098
+ case "ChainExpression":
1099
+ return evalExpression(node.expression, scope);
1100
+ case "MemberExpression": {
1101
+ let obj = evalExpression(node.object, scope);
1102
+ if ((obj == null || obj === void 0) && node.optional) return void 0;
1103
+ const key = node.computed ? toKey(evalExpression(node.property, scope)) : node.property.name;
1104
+ obj = unwrapRefForMember(obj, key);
1105
+ return getMember(obj, key);
1106
+ }
1107
+ case "CallExpression": {
1108
+ const args = [];
1109
+ for (const a of node.arguments) {
1110
+ if (a.type === "SpreadElement") {
1111
+ const spread = evalExpression(a.argument, scope);
1112
+ if (!Array.isArray(spread)) fail("Spread in calls must be an array");
1113
+ args.push(...spread);
1114
+ } else {
1115
+ args.push(evalExpression(a, scope));
1116
+ }
1117
+ }
1118
+ if (node.callee.type === "Identifier") {
1119
+ const name = node.callee.name;
1120
+ assertSafeIdentifier(name);
1121
+ const fn = getVar(scope, name);
1122
+ if (typeof fn !== "function") {
1123
+ if (node.optional) return void 0;
1124
+ return void 0;
1125
+ }
1126
+ return fn.apply(scope.ctx, args);
1127
+ }
1128
+ if (node.callee.type === "MemberExpression") {
1129
+ let obj = evalExpression(node.callee.object, scope);
1130
+ if ((obj == null || obj === void 0) && node.optional) return void 0;
1131
+ const key = node.callee.computed ? toKey(evalExpression(node.callee.property, scope)) : node.callee.property.name;
1132
+ obj = unwrapRefForMember(obj, key);
1133
+ const fn = getMember(obj, key);
1134
+ if (typeof fn !== "function") {
1135
+ if (node.optional) return void 0;
1136
+ return void 0;
1137
+ }
1138
+ return fn.apply(obj, args);
1139
+ }
1140
+ fail("Unsupported call target: " + node.callee.type);
1141
+ }
1142
+ case "ConditionalExpression":
1143
+ return evalExpression(node.test, scope) ? evalExpression(node.consequent, scope) : evalExpression(node.alternate, scope);
1144
+ case "LogicalExpression": {
1145
+ const left = evalExpression(node.left, scope);
1146
+ if (node.operator === "&&")
1147
+ return left && evalExpression(node.right, scope);
1148
+ if (node.operator === "||")
1149
+ return left || evalExpression(node.right, scope);
1150
+ if (node.operator === "??")
1151
+ return left ?? evalExpression(node.right, scope);
1152
+ fail("Unsupported logical op: " + node.operator);
1153
+ }
1154
+ case "BinaryExpression":
1155
+ return evalBinary(
1156
+ node.operator,
1157
+ evalExpression(node.left, scope),
1158
+ evalExpression(node.right, scope)
1159
+ );
1160
+ case "UnaryExpression":
1161
+ return evalUnary(
1162
+ node.operator,
1163
+ evalExpression(node.argument, scope)
1164
+ );
1165
+ case "UpdateExpression": {
1166
+ const lv = resolveLValue(node.argument, scope);
1167
+ const oldVal = lv.get();
1168
+ const n = Number(oldVal);
1169
+ const nextVal = node.operator === "++" ? n + 1 : n - 1;
1170
+ lv.set(nextVal);
1171
+ return node.prefix ? nextVal : oldVal;
1172
+ }
1173
+ case "AssignmentExpression": {
1174
+ const lv = resolveLValue(node.left, scope);
1175
+ const right = evalExpression(node.right, scope);
1176
+ const next = applyAssignment(node.operator, lv.get(), right);
1177
+ lv.set(next);
1178
+ return next;
1179
+ }
1180
+ case "SequenceExpression": {
1181
+ let v;
1182
+ for (const ex of node.expressions) v = evalExpression(ex, scope);
1183
+ return v;
1184
+ }
1185
+ case "ParenthesizedExpression":
1186
+ return evalExpression(node.expression, scope);
1187
+ default:
1188
+ fail("Unsupported expr node: " + node.type);
1189
+ }
1190
+ }
1191
+
1192
+ // src/ast/eval-expression-async.ts
1193
+ async function evalExpressionAsync(node, scope, meta) {
1194
+ if (node?.type === "AwaitExpression") {
1195
+ const v = evalExpression(node.argument, scope);
1196
+ return await Promise.resolve(v);
1197
+ }
1198
+ return evalExpression(node, scope);
1199
+ }
1200
+
1201
+ // src/ast/flow-control.ts
1202
+ var SIG_RETURN = /* @__PURE__ */ Symbol("return");
1203
+ var SIG_BREAK = /* @__PURE__ */ Symbol("break");
1204
+ var SIG_CONTINUE = /* @__PURE__ */ Symbol("continue");
1205
+ function sigReturn(value) {
1206
+ return { t: SIG_RETURN, v: value };
1207
+ }
1208
+ function sigBreak() {
1209
+ return { t: SIG_BREAK };
1210
+ }
1211
+ function sigContinue() {
1212
+ return { t: SIG_CONTINUE };
1213
+ }
1214
+ function isReturn(r) {
1215
+ return r != null && typeof r === "object" && r.t === SIG_RETURN;
1216
+ }
1217
+ function isBreak(r) {
1218
+ return r != null && typeof r === "object" && r.t === SIG_BREAK;
1219
+ }
1220
+ function isContinue(r) {
1221
+ return r != null && typeof r === "object" && r.t === SIG_CONTINUE;
1222
+ }
1223
+
1224
+ // src/ast/exec-statement.ts
1225
+ function execSwitch(node, scope, meta) {
1226
+ const discriminant = evalExpression(node.discriminant, scope);
1227
+ let matched = false;
1228
+ for (const caseNode of node.cases) {
1229
+ if (!matched) {
1230
+ if (caseNode.test) {
1231
+ if (evalExpression(caseNode.test, scope) !== discriminant) continue;
1232
+ matched = true;
1233
+ } else {
1234
+ matched = true;
1235
+ }
1236
+ }
1237
+ if (matched) {
1238
+ for (const stmt of caseNode.consequent) {
1239
+ const r = execStatement(stmt, scope, meta);
1240
+ if (isReturn(r)) return r;
1241
+ if (isBreak(r)) return;
1242
+ }
1243
+ }
1244
+ }
1245
+ return;
1246
+ }
1247
+ function execStatement(node, scope, meta) {
1248
+ switch (node.type) {
1249
+ case "Program": {
1250
+ for (const s of node.body) {
1251
+ const r = execStatement(s, scope, meta);
1252
+ if (isReturn(r)) return r;
1253
+ }
1254
+ return;
1255
+ }
1256
+ case "BlockStatement": {
1257
+ const child = createScope(scope.ctx, Object.create(scope.locals));
1258
+ for (const s of node.body) {
1259
+ const r = execStatement(s, child, meta);
1260
+ if (isReturn(r)) return r;
1261
+ if (isBreak(r) || isContinue(r)) return r;
1262
+ }
1263
+ return;
1264
+ }
1265
+ case "ExpressionStatement":
1266
+ return evalExpression(node.expression, scope);
1267
+ case "EmptyStatement":
1268
+ return;
1269
+ case "IfStatement": {
1270
+ const ok = !!evalExpression(node.test, scope);
1271
+ if (ok) return execStatement(node.consequent, scope, meta);
1272
+ if (node.alternate) return execStatement(node.alternate, scope, meta);
1273
+ return;
1274
+ }
1275
+ case "ReturnStatement":
1276
+ return sigReturn(
1277
+ node.argument ? evalExpression(node.argument, scope) : void 0
1278
+ );
1279
+ case "ThrowStatement":
1280
+ throw evalExpression(node.argument, scope);
1281
+ case "BreakStatement":
1282
+ return sigBreak();
1283
+ case "ContinueStatement":
1284
+ return sigContinue();
1285
+ case "SwitchStatement":
1286
+ return execSwitch(node, scope, meta);
1287
+ case "TryStatement": {
1288
+ try {
1289
+ const r = execStatement(node.block, scope, meta);
1290
+ if (isReturn(r)) return r;
1291
+ } catch (err) {
1292
+ if (node.handler) {
1293
+ const child = createScope(scope.ctx, Object.create(scope.locals));
1294
+ const param = node.handler.param;
1295
+ if (param?.type === "Identifier") {
1296
+ assertSafeIdentifier(param.name);
1297
+ child.locals[param.name] = err;
1298
+ }
1299
+ const r = execStatement(node.handler.body, child, meta);
1300
+ if (isReturn(r)) return r;
1301
+ } else {
1302
+ throw err;
1303
+ }
1304
+ } finally {
1305
+ if (node.finalizer) execStatement(node.finalizer, scope, meta);
1306
+ }
1307
+ return;
1308
+ }
1309
+ case "VariableDeclaration": {
1310
+ for (const d of node.declarations) {
1311
+ if (d.id.type !== "Identifier") fail("Only simple var names supported");
1312
+ const name = d.id.name;
1313
+ assertSafeIdentifier(name);
1314
+ scope.locals[name] = d.init ? evalExpression(d.init, scope) : void 0;
1315
+ }
1316
+ return;
1317
+ }
1318
+ case "ForStatement": {
1319
+ if (node.init) {
1320
+ if (node.init.type === "VariableDeclaration") {
1321
+ execStatement(node.init, scope, meta);
1322
+ } else {
1323
+ evalExpression(node.init, scope);
1324
+ }
1325
+ }
1326
+ for (; ; ) {
1327
+ if (node.test && !evalExpression(node.test, scope)) break;
1328
+ const r = execStatement(node.body, scope, meta);
1329
+ if (isReturn(r)) return r;
1330
+ if (isBreak(r)) break;
1331
+ if (isContinue(r)) {
1332
+ if (node.update) evalExpression(node.update, scope);
1333
+ continue;
1334
+ }
1335
+ if (node.update) evalExpression(node.update, scope);
1336
+ }
1337
+ return;
1338
+ }
1339
+ case "WhileStatement": {
1340
+ while (evalExpression(node.test, scope)) {
1341
+ const r = execStatement(node.body, scope, meta);
1342
+ if (isReturn(r)) return r;
1343
+ if (isBreak(r)) break;
1344
+ if (isContinue(r)) continue;
1345
+ }
1346
+ return;
1347
+ }
1348
+ case "DoWhileStatement": {
1349
+ do {
1350
+ const r = execStatement(node.body, scope, meta);
1351
+ if (isReturn(r)) return r;
1352
+ if (isBreak(r)) break;
1353
+ if (isContinue(r)) continue;
1354
+ } while (evalExpression(node.test, scope));
1355
+ return;
1356
+ }
1357
+ case "ForInStatement": {
1358
+ const src = evalExpression(node.right, scope);
1359
+ if (src == null || typeof src !== "object") return;
1360
+ for (const key in src) {
1361
+ if (node.left.type !== "Identifier") {
1362
+ fail("for-in requires Identifier binding");
1363
+ }
1364
+ assertSafeIdentifier(node.left.name);
1365
+ scope.locals[node.left.name] = key;
1366
+ const r = execStatement(node.body, scope, meta);
1367
+ if (isReturn(r)) return r;
1368
+ if (isBreak(r)) break;
1369
+ if (isContinue(r)) continue;
1370
+ }
1371
+ return;
1372
+ }
1373
+ case "ForOfStatement": {
1374
+ const src = evalExpression(node.right, scope);
1375
+ if (src == null || typeof src !== "object" || !(Symbol.iterator in Object(src))) {
1376
+ return;
1377
+ }
1378
+ for (const value of src) {
1379
+ if (node.left.type === "Identifier") {
1380
+ assertSafeIdentifier(node.left.name);
1381
+ scope.locals[node.left.name] = value;
1382
+ } else if (node.left.type === "VariableDeclaration") {
1383
+ const d = node.left.declarations[0];
1384
+ if (!d || d.id.type !== "Identifier") fail("for-of requires simple binding");
1385
+ assertSafeIdentifier(d.id.name);
1386
+ scope.locals[d.id.name] = value;
1387
+ } else {
1388
+ fail("for-of requires Identifier or var binding");
1389
+ }
1390
+ const r = execStatement(node.body, scope, meta);
1391
+ if (isReturn(r)) return r;
1392
+ if (isBreak(r)) break;
1393
+ if (isContinue(r)) continue;
1394
+ }
1395
+ return;
1396
+ }
1397
+ default:
1398
+ fail("Unsupported stmt node: " + node.type);
1399
+ }
1400
+ }
1401
+
1402
+ // src/ast/exec-statement-async.ts
1403
+ async function execSwitchAsync(node, scope, meta) {
1404
+ const discriminant = await evalExpressionAsync(node.discriminant, scope);
1405
+ let matched = false;
1406
+ for (const caseNode of node.cases) {
1407
+ if (!matched) {
1408
+ if (caseNode.test) {
1409
+ if (await evalExpressionAsync(caseNode.test, scope) !== discriminant) {
1410
+ continue;
1411
+ }
1412
+ matched = true;
1413
+ } else {
1414
+ matched = true;
1415
+ }
1416
+ }
1417
+ if (matched) {
1418
+ for (const stmt of caseNode.consequent) {
1419
+ const r = await execStatementAsync(stmt, scope, meta);
1420
+ if (isReturn(r)) return r;
1421
+ if (isBreak(r)) return;
1422
+ }
1423
+ }
1424
+ }
1425
+ return;
1426
+ }
1427
+ async function execStatementAsync(node, scope, meta) {
1428
+ switch (node.type) {
1429
+ case "Program": {
1430
+ for (const s of node.body) {
1431
+ const r = await execStatementAsync(s, scope, meta);
1432
+ if (isReturn(r)) return r;
1433
+ }
1434
+ return;
1435
+ }
1436
+ case "BlockStatement": {
1437
+ const child = createScope(scope.ctx, Object.create(scope.locals));
1438
+ for (const s of node.body) {
1439
+ const r = await execStatementAsync(s, child, meta);
1440
+ if (isReturn(r)) return r;
1441
+ if (isBreak(r) || isContinue(r)) return r;
1442
+ }
1443
+ return;
1444
+ }
1445
+ case "ExpressionStatement":
1446
+ return await evalExpressionAsync(node.expression, scope);
1447
+ case "EmptyStatement":
1448
+ return;
1449
+ case "IfStatement": {
1450
+ const ok = !!await evalExpressionAsync(node.test, scope);
1451
+ if (ok) return await execStatementAsync(node.consequent, scope, meta);
1452
+ if (node.alternate) return await execStatementAsync(node.alternate, scope, meta);
1453
+ return;
1454
+ }
1455
+ case "ReturnStatement":
1456
+ return sigReturn(
1457
+ node.argument ? await evalExpressionAsync(node.argument, scope) : void 0
1458
+ );
1459
+ case "ThrowStatement":
1460
+ throw await evalExpressionAsync(node.argument, scope);
1461
+ case "BreakStatement":
1462
+ return sigBreak();
1463
+ case "ContinueStatement":
1464
+ return sigContinue();
1465
+ case "SwitchStatement":
1466
+ return await execSwitchAsync(node, scope, meta);
1467
+ case "TryStatement": {
1468
+ try {
1469
+ const r = await execStatementAsync(node.block, scope, meta);
1470
+ if (isReturn(r)) return r;
1471
+ } catch (err) {
1472
+ if (node.handler) {
1473
+ const child = createScope(scope.ctx, Object.create(scope.locals));
1474
+ const param = node.handler.param;
1475
+ if (param?.type === "Identifier") {
1476
+ assertSafeIdentifier(param.name);
1477
+ child.locals[param.name] = err;
1478
+ }
1479
+ const r = await execStatementAsync(node.handler.body, child, meta);
1480
+ if (isReturn(r)) return r;
1481
+ } else {
1482
+ throw err;
1483
+ }
1484
+ } finally {
1485
+ if (node.finalizer) await execStatementAsync(node.finalizer, scope, meta);
1486
+ }
1487
+ return;
1488
+ }
1489
+ case "VariableDeclaration": {
1490
+ for (const d of node.declarations) {
1491
+ if (d.id.type !== "Identifier") fail("Only simple var names supported");
1492
+ const name = d.id.name;
1493
+ assertSafeIdentifier(name);
1494
+ scope.locals[name] = d.init ? await evalExpressionAsync(d.init, scope) : void 0;
1495
+ }
1496
+ return;
1497
+ }
1498
+ case "ForStatement": {
1499
+ if (node.init) {
1500
+ if (node.init.type === "VariableDeclaration") {
1501
+ await execStatementAsync(node.init, scope, meta);
1502
+ } else {
1503
+ await evalExpressionAsync(node.init, scope);
1504
+ }
1505
+ }
1506
+ for (; ; ) {
1507
+ if (node.test && !await evalExpressionAsync(node.test, scope)) break;
1508
+ const r = await execStatementAsync(node.body, scope, meta);
1509
+ if (isReturn(r)) return r;
1510
+ if (isBreak(r)) break;
1511
+ if (isContinue(r)) {
1512
+ if (node.update) await evalExpressionAsync(node.update, scope);
1513
+ continue;
1514
+ }
1515
+ if (node.update) await evalExpressionAsync(node.update, scope);
1516
+ }
1517
+ return;
1518
+ }
1519
+ case "WhileStatement": {
1520
+ while (await evalExpressionAsync(node.test, scope)) {
1521
+ const r = await execStatementAsync(node.body, scope, meta);
1522
+ if (isReturn(r)) return r;
1523
+ if (isBreak(r)) break;
1524
+ if (isContinue(r)) continue;
1525
+ }
1526
+ return;
1527
+ }
1528
+ case "DoWhileStatement": {
1529
+ do {
1530
+ const r = await execStatementAsync(node.body, scope, meta);
1531
+ if (isReturn(r)) return r;
1532
+ if (isBreak(r)) break;
1533
+ if (isContinue(r)) continue;
1534
+ } while (await evalExpressionAsync(node.test, scope));
1535
+ return;
1536
+ }
1537
+ case "ForInStatement": {
1538
+ const src = await evalExpressionAsync(node.right, scope);
1539
+ if (src == null || typeof src !== "object") return;
1540
+ for (const key in src) {
1541
+ if (node.left.type !== "Identifier") fail("for-in requires Identifier binding");
1542
+ assertSafeIdentifier(node.left.name);
1543
+ scope.locals[node.left.name] = key;
1544
+ const r = await execStatementAsync(node.body, scope, meta);
1545
+ if (isReturn(r)) return r;
1546
+ if (isBreak(r)) break;
1547
+ if (isContinue(r)) continue;
1548
+ }
1549
+ return;
1550
+ }
1551
+ case "ForOfStatement": {
1552
+ const src = await evalExpressionAsync(node.right, scope);
1553
+ if (src == null || typeof src !== "object" || !(Symbol.iterator in Object(src))) {
1554
+ return;
1555
+ }
1556
+ for (const value of src) {
1557
+ if (node.left.type === "Identifier") {
1558
+ assertSafeIdentifier(node.left.name);
1559
+ scope.locals[node.left.name] = value;
1560
+ } else if (node.left.type === "VariableDeclaration") {
1561
+ const d = node.left.declarations[0];
1562
+ if (!d || d.id.type !== "Identifier") fail("for-of requires simple binding");
1563
+ assertSafeIdentifier(d.id.name);
1564
+ scope.locals[d.id.name] = value;
1565
+ } else {
1566
+ fail("for-of requires Identifier or var binding");
1567
+ }
1568
+ const r = await execStatementAsync(node.body, scope, meta);
1569
+ if (isReturn(r)) return r;
1570
+ if (isBreak(r)) break;
1571
+ if (isContinue(r)) continue;
1572
+ }
1573
+ return;
1574
+ }
1575
+ default:
1576
+ fail("Unsupported stmt node: " + node.type);
1577
+ }
1578
+ }
1579
+
1580
+ // src/ast/context-eval.ts
1581
+ function evalInCtxAst(ast, ctx, $event, $el, debugLabel = "") {
1582
+ try {
1583
+ const locals = /* @__PURE__ */ Object.create(null);
1584
+ locals.$event = $event;
1585
+ locals.$el = $el;
1586
+ const scope = createScope(ctx, locals);
1587
+ return evalExpression(ast, scope, { debugLabel });
1588
+ } catch (err) {
1589
+ logError(WarnCodes.AST_EVAL, err, {
1590
+ label: debugLabel || "expression"
1591
+ });
1592
+ return void 0;
1593
+ }
1594
+ }
1595
+ function runInCtxAst(programAst, ctx, $event, $el, debugLabel = "") {
1596
+ try {
1597
+ const locals = /* @__PURE__ */ Object.create(null);
1598
+ locals.$event = $event;
1599
+ locals.$el = $el;
1600
+ const scope = createScope(ctx, locals);
1601
+ const r = execStatement(programAst, scope, { debugLabel });
1602
+ return r && r.t === SIG_RETURN ? r.v : r;
1603
+ } catch (err) {
1604
+ logError(WarnCodes.AST_STMT, err, {
1605
+ label: debugLabel || "statement"
1606
+ });
1607
+ return void 0;
1608
+ }
1609
+ }
1610
+ async function runInCtxAstAsync(programAst, ctx, $event, $el, debugLabel = "") {
1611
+ try {
1612
+ const locals = /* @__PURE__ */ Object.create(null);
1613
+ locals.$event = $event;
1614
+ locals.$el = $el;
1615
+ const scope = createScope(ctx, locals);
1616
+ const r = await execStatementAsync(programAst, scope, {
1617
+ debugLabel
1618
+ });
1619
+ return r && r.t === SIG_RETURN ? r.v : r;
1620
+ } catch (err) {
1621
+ logError(WarnCodes.AST_STMT, err, {
1622
+ label: debugLabel || "statement"
1623
+ });
1624
+ return void 0;
1625
+ }
1626
+ }
1627
+
1628
+ // src/runtime/registry.ts
1629
+ function skyNode(node) {
1630
+ return node;
1631
+ }
1632
+ function register(node, fn) {
1633
+ (skyNode(node).__skyCleanup ??= []).push(fn);
1634
+ }
1635
+ function cleanup(node) {
1636
+ skyNode(node).__skyCleanup?.forEach((fn) => fn());
1637
+ if (node.childNodes) Array.from(node.childNodes).forEach(cleanup);
1638
+ }
1639
+ function autoEffect(node, fn) {
1640
+ const runner = effect(fn);
1641
+ register(node, () => runner.stop());
1642
+ return runner;
1643
+ }
1644
+
1645
+ // src/runtime/normalize.ts
1646
+ function normalizeClass(val) {
1647
+ if (!val) return "";
1648
+ if (typeof val === "string") return val;
1649
+ if (Array.isArray(val))
1650
+ return val.filter(Boolean).map(normalizeClass).join(" ");
1651
+ if (typeof val === "object")
1652
+ return Object.keys(val).filter((k) => val[k]).join(" ");
1653
+ return "";
1654
+ }
1655
+ function normalizeStyle(val) {
1656
+ if (!val) return {};
1657
+ if (typeof val === "string") return val;
1658
+ if (typeof val === "object") return val;
1659
+ return {};
1660
+ }
1661
+ function isTextInputLike(el) {
1662
+ return el.nodeType === 1 && (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT");
1663
+ }
1664
+ function isCustomElement(el) {
1665
+ return el.tagName.includes("-");
1666
+ }
1667
+ function deepTrack(val, seen = /* @__PURE__ */ new Set()) {
1668
+ val = unref(val);
1669
+ if (!val || typeof val !== "object" || seen.has(val)) return;
1670
+ seen.add(val);
1671
+ if (Array.isArray(val)) {
1672
+ val.length;
1673
+ for (let i = 0; i < val.length; i++) deepTrack(val[i], seen);
1674
+ } else {
1675
+ const record = val;
1676
+ for (const k in record) deepTrack(record[k], seen);
1677
+ }
1678
+ }
1679
+ function cloneShallow(val) {
1680
+ val = unref(val);
1681
+ if (Array.isArray(val)) return val.slice();
1682
+ if (val && typeof val === "object") return { ...val };
1683
+ return val;
1684
+ }
1685
+
1686
+ // src/runtime/text-template.ts
1687
+ function compileTextTemplate(raw) {
1688
+ const tokens = [];
1689
+ let last = 0;
1690
+ raw.replace(/{{(.*?)}}/g, (m, expr, idx) => {
1691
+ if (idx > last) tokens.push({ t: "text", v: raw.slice(last, idx) });
1692
+ tokens.push({ t: "expr", ast: compileExpr(expr) });
1693
+ last = idx + m.length;
1694
+ return m;
1695
+ });
1696
+ if (last < raw.length) tokens.push({ t: "text", v: raw.slice(last) });
1697
+ return function render(ctx, $el) {
1698
+ let out = "";
1699
+ for (const tok of tokens) {
1700
+ if (tok.t === "text") out += tok.v;
1701
+ else {
1702
+ const v = evalInCtxAst(tok.ast, ctx, void 0, $el, "text");
1703
+ out += v == null ? "" : String(v);
1704
+ }
1705
+ }
1706
+ return out;
1707
+ };
1708
+ }
1709
+
1710
+ // src/runtime/for-utils.ts
1711
+ function kebabToCamel(s) {
1712
+ return s.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
1713
+ }
1714
+ function parseForAlias(lhsRaw) {
1715
+ const lhs = (lhsRaw || "").trim();
1716
+ const tuple = lhs.match(
1717
+ /^\(\s*([A-Za-z_$][\w$]*)\s*,\s*([A-Za-z_$][\w$]*)\s*\)$/
1718
+ );
1719
+ if (tuple) return { item: tuple[1], index: tuple[2] };
1720
+ const single = lhs.match(/^([A-Za-z_$][\w$]*)$/);
1721
+ if (single) return { item: single[1], index: null };
1722
+ throw new Error(
1723
+ "sky-for syntax error. Use `item in items` or `(item, index) in items`"
1724
+ );
1725
+ }
1726
+ function normalizeForSource(source, indexAlias) {
1727
+ if (source === null || source === void 0) {
1728
+ return [];
1729
+ }
1730
+ if (Array.isArray(source)) {
1731
+ return source.map((value, index) => ({
1732
+ value,
1733
+ key: index,
1734
+ extra: indexAlias ? { [indexAlias]: index } : {}
1735
+ }));
1736
+ }
1737
+ if (typeof source === "number" && !Number.isNaN(source)) {
1738
+ const items = [];
1739
+ const n = Math.floor(Math.abs(source));
1740
+ for (let i = 0; i < n; i++) {
1741
+ items.push({
1742
+ value: i,
1743
+ key: i,
1744
+ extra: indexAlias ? { [indexAlias]: i } : {}
1745
+ });
1746
+ }
1747
+ return items;
1748
+ }
1749
+ if (typeof source === "string") {
1750
+ return Array.from(source).map((char, index) => ({
1751
+ value: char,
1752
+ key: index,
1753
+ extra: indexAlias ? { [indexAlias]: index } : {}
1754
+ }));
1755
+ }
1756
+ if (typeof source === "object") {
1757
+ const record = source;
1758
+ const keys = Object.keys(record);
1759
+ return keys.map((key, index) => ({
1760
+ value: record[key],
1761
+ key,
1762
+ extra: {
1763
+ $key: key,
1764
+ ...indexAlias ? { [indexAlias]: index } : {}
1765
+ }
1766
+ }));
1767
+ }
1768
+ return [
1769
+ {
1770
+ value: source,
1771
+ key: 0,
1772
+ extra: indexAlias ? { [indexAlias]: 0 } : {}
1773
+ }
1774
+ ];
1775
+ }
1776
+
1777
+ // src/runtime/prop-map.ts
1778
+ var PROP_NAME_CACHE = /* @__PURE__ */ new WeakMap();
1779
+ function buildPropMapFor(el) {
1780
+ const map = /* @__PURE__ */ new Map();
1781
+ let proto = el;
1782
+ while (proto && proto !== Object.prototype) {
1783
+ for (const k of Object.getOwnPropertyNames(proto)) {
1784
+ map.set(k.toLowerCase(), k);
1785
+ }
1786
+ proto = Object.getPrototypeOf(proto);
1787
+ }
1788
+ return map;
1789
+ }
1790
+ function resolveDomPropName(el, raw) {
1791
+ if (raw.includes("-")) return kebabToCamel(raw);
1792
+ const lower = raw.toLowerCase();
1793
+ let map = PROP_NAME_CACHE.get(el.constructor);
1794
+ if (!map) {
1795
+ map = buildPropMapFor(el);
1796
+ PROP_NAME_CACHE.set(el.constructor, map);
1797
+ }
1798
+ return map.get(lower) ?? raw;
1799
+ }
1800
+
1801
+ // src/runtime/dom.ts
1802
+ var NODE_ELEMENT = 1;
1803
+ var NODE_TEXT = 3;
1804
+ function isElement(node) {
1805
+ return node.nodeType === NODE_ELEMENT;
1806
+ }
1807
+ function isTextNode(node) {
1808
+ return node.nodeType === NODE_TEXT;
1809
+ }
1810
+ function asHtmlEl(node) {
1811
+ return node;
1812
+ }
1813
+ function tagName(el) {
1814
+ return el.tagName.toUpperCase();
1815
+ }
1816
+ function inputType(el) {
1817
+ return (el.getAttribute("type") || "text").toLowerCase();
1818
+ }
1819
+ function inputField(el) {
1820
+ return el;
1821
+ }
1822
+ function createComment(ref2, data) {
1823
+ const doc = ref2.ownerDocument;
1824
+ if (!doc) {
1825
+ throw new Error("[Sky] Node has no ownerDocument");
1826
+ }
1827
+ return doc.createComment(data);
1828
+ }
1829
+
1830
+ // src/runtime/model-parse.ts
1831
+ var SKY_MODEL_MODIFIERS = /* @__PURE__ */ new Set(["lazy", "number", "trim"]);
1832
+ function unknownModifierSegments(parts) {
1833
+ return parts.filter((p) => !SKY_MODEL_MODIFIERS.has(p));
1834
+ }
1835
+ function parseSkyModelAttr(attrName, value) {
1836
+ const key = value.trim();
1837
+ if (!key || !/^[A-Za-z_$][\w$]*$/.test(key)) {
1838
+ return null;
1839
+ }
1840
+ if (attrName === "sky-model") {
1841
+ return { key, arg: null, modifiers: [], unknownModifiers: [] };
1842
+ }
1843
+ let rest = null;
1844
+ if (attrName.startsWith("sky-model:")) {
1845
+ rest = attrName.slice("sky-model:".length);
1846
+ } else if (attrName.startsWith("sky-model.")) {
1847
+ rest = attrName.slice("sky-model.".length);
1848
+ } else {
1849
+ return null;
1850
+ }
1851
+ if (!rest) {
1852
+ return { key, arg: null, modifiers: [], unknownModifiers: [] };
1853
+ }
1854
+ const parts = rest.split(".").filter((p) => p.length > 0);
1855
+ if (parts.length === 0) {
1856
+ return { key, arg: null, modifiers: [], unknownModifiers: [] };
1857
+ }
1858
+ const first = parts[0];
1859
+ if (SKY_MODEL_MODIFIERS.has(first)) {
1860
+ return {
1861
+ key,
1862
+ arg: null,
1863
+ modifiers: normalizeSkyModelModifiers(parts),
1864
+ unknownModifiers: unknownModifierSegments(parts)
1865
+ };
1866
+ }
1867
+ return {
1868
+ key,
1869
+ arg: first,
1870
+ modifiers: normalizeSkyModelModifiers(parts.slice(1)),
1871
+ unknownModifiers: unknownModifierSegments(parts.slice(1))
1872
+ };
1873
+ }
1874
+ function isSkyModelAttr(attrName) {
1875
+ return attrName === "sky-model" || attrName.startsWith("sky-model.") || attrName.startsWith("sky-model:");
1876
+ }
1877
+ function normalizeSkyModelModifiers(modifiers) {
1878
+ const out = [];
1879
+ for (const m of modifiers) {
1880
+ if (SKY_MODEL_MODIFIERS.has(m) && !out.includes(m)) {
1881
+ out.push(m);
1882
+ }
1883
+ }
1884
+ return out;
1885
+ }
1886
+ function coerceModelWriteValue(value, modifiers) {
1887
+ const mods = normalizeSkyModelModifiers(modifiers);
1888
+ let v = value;
1889
+ if (mods.includes("trim") && typeof v === "string") {
1890
+ v = v.trim();
1891
+ }
1892
+ if (mods.includes("number")) {
1893
+ if (v === "" || v == null) {
1894
+ return "";
1895
+ }
1896
+ const n = typeof v === "number" ? v : Number(v);
1897
+ return Number.isNaN(n) ? v : n;
1898
+ }
1899
+ return v;
1900
+ }
1901
+ function coerceModelPropValue(value, modifiers) {
1902
+ const v = value == null ? void 0 : value;
1903
+ const mods = normalizeSkyModelModifiers(modifiers);
1904
+ if (mods.includes("number") && v !== "" && v != null) {
1905
+ const n = typeof v === "number" ? v : Number(v);
1906
+ return Number.isNaN(n) ? v : n;
1907
+ }
1908
+ return v;
1909
+ }
1910
+
1911
+ // src/runtime/model.ts
1912
+ function bindSkyModel(el, ctx, key, modifiers = []) {
1913
+ const mods = normalizeSkyModelModifiers(modifiers);
1914
+ const field = inputField(el);
1915
+ const tag = tagName(el);
1916
+ const type = inputType(el);
1917
+ if (tag === "INPUT" && type === "checkbox") {
1918
+ return {
1919
+ event: "change",
1920
+ read: () => {
1921
+ field.checked = Boolean(unref(ctx[key]));
1922
+ }
1923
+ };
1924
+ }
1925
+ if (tag === "INPUT" && type === "radio") {
1926
+ return {
1927
+ event: "change",
1928
+ read: () => {
1929
+ const v = unref(ctx[key]);
1930
+ field.checked = field.value === String(v ?? "");
1931
+ }
1932
+ };
1933
+ }
1934
+ if (tag === "SELECT") {
1935
+ return {
1936
+ event: "change",
1937
+ read: () => {
1938
+ const v = unref(ctx[key]);
1939
+ field.value = v == null ? "" : String(v);
1940
+ }
1941
+ };
1942
+ }
1943
+ if (tag === "INPUT" || tag === "TEXTAREA") {
1944
+ const event = mods.includes("lazy") ? "change" : "input";
1945
+ return {
1946
+ event,
1947
+ read: () => {
1948
+ const v = unref(ctx[key]);
1949
+ const str = v == null ? "" : String(v);
1950
+ if (field.value !== str) field.value = str;
1951
+ }
1952
+ };
1953
+ }
1954
+ return { event: "input", read: () => {
1955
+ } };
1956
+ }
1957
+ function readModelValue(el) {
1958
+ const field = inputField(el);
1959
+ if (tagName(el) === "INPUT" && inputType(el) === "checkbox") return field.checked;
1960
+ if (tagName(el) === "INPUT" && inputType(el) === "radio") return field.value;
1961
+ if (tagName(el) === "SELECT") return field.value;
1962
+ if (tagName(el) === "INPUT" || tagName(el) === "TEXTAREA") return field.value;
1963
+ return void 0;
1964
+ }
1965
+ function writeModelValue(ctx, key, el, value, modifiers = []) {
1966
+ const field = inputField(el);
1967
+ if (tagName(el) === "INPUT" && inputType(el) === "radio" && !field.checked) {
1968
+ return;
1969
+ }
1970
+ const coerced = coerceModelWriteValue(value, modifiers);
1971
+ const cur = ctx[key];
1972
+ if (isRef(cur)) cur.value = coerced;
1973
+ else ctx[key] = coerced;
1974
+ }
1975
+
1976
+ // src/runtime/model-custom.ts
1977
+ function resolveModelPropAndEvent(el, arg) {
1978
+ const prop = arg ? resolveDomPropName(el, arg) : "modelValue";
1979
+ return { prop, eventName: `update:${prop}` };
1980
+ }
1981
+ function bindCustomSkyModel(el, ctx, key, arg, modifiers = []) {
1982
+ const mods = normalizeSkyModelModifiers(modifiers);
1983
+ const { prop, eventName } = resolveModelPropAndEvent(el, arg);
1984
+ const target = el;
1985
+ const read = () => {
1986
+ target[prop] = coerceModelPropValue(unref(ctx[key]), mods);
1987
+ };
1988
+ const onUpdate = (e) => {
1989
+ const ce = e;
1990
+ let val = ce.detail;
1991
+ if (val === void 0 && e.target) {
1992
+ val = e.target[prop];
1993
+ }
1994
+ writeModelValue(ctx, key, el, val, mods);
1995
+ };
1996
+ return { prop, eventName, read, onUpdate };
1997
+ }
1998
+
1999
+ // src/runtime/events.ts
2000
+ var DOM_EVENT_MODS = /* @__PURE__ */ new Set([
2001
+ "prevent",
2002
+ "stop",
2003
+ "self",
2004
+ "once",
2005
+ "exact",
2006
+ "capture",
2007
+ "passive",
2008
+ "ctrl",
2009
+ "alt",
2010
+ "shift",
2011
+ "meta"
2012
+ ]);
2013
+ var WRAP_MODS = DOM_EVENT_MODS;
2014
+ function getListenerOptions(modifiers) {
2015
+ const opts = {};
2016
+ if (modifiers.includes("capture")) opts.capture = true;
2017
+ if (modifiers.includes("passive")) opts.passive = true;
2018
+ return Object.keys(opts).length > 0 ? opts : false;
2019
+ }
2020
+ var KEY_ALIAS = {
2021
+ enter: "Enter",
2022
+ tab: "Tab",
2023
+ delete: "Delete",
2024
+ del: "Delete",
2025
+ esc: "Escape",
2026
+ escape: "Escape",
2027
+ space: " ",
2028
+ up: "ArrowUp",
2029
+ down: "ArrowDown",
2030
+ left: "ArrowLeft",
2031
+ right: "ArrowRight"
2032
+ };
2033
+ function isKeyLikeModifier(mod) {
2034
+ if (WRAP_MODS.has(mod)) return false;
2035
+ return mod.length >= 1;
2036
+ }
2037
+ function getKeyModifiers(modifiers) {
2038
+ return modifiers.filter(isKeyLikeModifier);
2039
+ }
2040
+ var KNOWN_EVENT_MODIFIERS = /* @__PURE__ */ new Set([
2041
+ ...DOM_EVENT_MODS,
2042
+ ...Object.keys(KEY_ALIAS),
2043
+ "ctrl",
2044
+ "alt",
2045
+ "shift",
2046
+ "meta"
2047
+ ]);
2048
+ function getUnknownEventModifiers(modifiers) {
2049
+ return modifiers.filter((m) => {
2050
+ if (KNOWN_EVENT_MODIFIERS.has(m)) return false;
2051
+ if (/^[a-z]$/i.test(m)) return false;
2052
+ return true;
2053
+ });
2054
+ }
2055
+ function systemModifierActive(e, mod) {
2056
+ switch (mod) {
2057
+ case "ctrl":
2058
+ return e.ctrlKey;
2059
+ case "alt":
2060
+ return e.altKey;
2061
+ case "shift":
2062
+ return e.shiftKey;
2063
+ case "meta":
2064
+ return e.metaKey;
2065
+ default:
2066
+ return false;
2067
+ }
2068
+ }
2069
+ function keyModifierMatches(e, mod) {
2070
+ if (["ctrl", "alt", "shift", "meta"].includes(mod)) {
2071
+ return systemModifierActive(e, mod);
2072
+ }
2073
+ const lower = mod.toLowerCase();
2074
+ const want = KEY_ALIAS[lower] ?? mod;
2075
+ if (e.key === want) return true;
2076
+ if (e.code === want) return true;
2077
+ if (want.length === 1 && e.key.toLowerCase() === want.toLowerCase()) return true;
2078
+ if (/^[a-z]$/i.test(want) && e.code === `Key${want.toUpperCase()}`) return true;
2079
+ return false;
2080
+ }
2081
+ function parseOnEventAttr(attrName) {
2082
+ if (!attrName.startsWith("on") || attrName.length <= 2) return null;
2083
+ const event = attrName.slice(2);
2084
+ return { event, modifiers: [], code: "" };
2085
+ }
2086
+ function parseAtEventAttr(attrName, code) {
2087
+ if (!attrName.startsWith("@")) return null;
2088
+ const parts = attrName.slice(1).split(".");
2089
+ const event = parts[0];
2090
+ if (!event) return null;
2091
+ return { event, modifiers: parts.slice(1), code };
2092
+ }
2093
+ function wrapEventHandler(handler, modifiers, node) {
2094
+ let wrapped = handler;
2095
+ if (modifiers.includes("once")) {
2096
+ wrapped = /* @__PURE__ */ ((fn) => {
2097
+ let called = false;
2098
+ return (e) => {
2099
+ if (called) return;
2100
+ called = true;
2101
+ fn(e);
2102
+ };
2103
+ })(wrapped);
2104
+ }
2105
+ const keyMods = getKeyModifiers(modifiers);
2106
+ return (e) => {
2107
+ if (modifiers.includes("self") && e.target !== node) return;
2108
+ if (modifiers.includes("exact")) {
2109
+ if (e.target !== node) return;
2110
+ if (e instanceof MouseEvent && e.button !== 0) return;
2111
+ }
2112
+ if (keyMods.length > 0 && "key" in e) {
2113
+ const ke = e;
2114
+ for (const mod of keyMods) {
2115
+ if (!keyModifierMatches(ke, mod)) return;
2116
+ }
2117
+ }
2118
+ if (modifiers.includes("prevent")) e.preventDefault();
2119
+ if (modifiers.includes("stop")) e.stopPropagation();
2120
+ wrapped(e);
2121
+ };
2122
+ }
2123
+
2124
+ // src/runtime/compile-mode.ts
2125
+ var mode = "client";
2126
+ function getCompileMode() {
2127
+ return mode;
2128
+ }
2129
+ function runInCompileMode(next, fn) {
2130
+ const prev = mode;
2131
+ mode = next;
2132
+ try {
2133
+ return fn();
2134
+ } finally {
2135
+ mode = prev;
2136
+ }
2137
+ }
2138
+
2139
+ // src/runtime/compile-node.ts
2140
+ function warnUnknownEventModifiers(node, binding, label) {
2141
+ for (const mod of getUnknownEventModifiers(binding.modifiers)) {
2142
+ warnOnce(
2143
+ WarnCodes.EVENT_UNKNOWN_MODIFIER,
2144
+ { mod, event: binding.event },
2145
+ { element: node, label }
2146
+ );
2147
+ }
2148
+ }
2149
+ function runHandler(code, ctx, node, label, e) {
2150
+ const program = compileStmt(code);
2151
+ const handlerUsesAwait = /\bawait\b/.test(code);
2152
+ if (handlerUsesAwait) {
2153
+ void runInCtxAstAsync(program, ctx, e, node, label).catch(
2154
+ (err) => logError(WarnCodes.HANDLER_RUNTIME, err, { element: node, label })
2155
+ );
2156
+ } else {
2157
+ runInCtxAst(program, ctx, e, node, label);
2158
+ }
2159
+ }
2160
+ function compileTextNode(node, ctx) {
2161
+ const raw = node.nodeValue ?? "";
2162
+ if (!raw.includes("{{")) return;
2163
+ const render = compileTextTemplate(raw);
2164
+ bindReactive(node, () => {
2165
+ node.nodeValue = render(ctx, node.parentElement);
2166
+ });
2167
+ }
2168
+ function compileChildren(parent, ctx) {
2169
+ for (const child of Array.from(parent.childNodes)) {
2170
+ if (isTextNode(child)) {
2171
+ compileTextNode(child, ctx);
2172
+ } else if (isElement(child)) {
2173
+ compileNode(child, ctx);
2174
+ }
2175
+ }
2176
+ }
2177
+ function bindReactive(node, fn, opts) {
2178
+ if (getCompileMode() === "ssr") {
2179
+ fn();
2180
+ return;
2181
+ }
2182
+ if (isElement(node) && node.hasAttribute("sky-once")) {
2183
+ if (isElement(node)) node.removeAttribute("sky-once");
2184
+ const runner = effect(() => {
2185
+ fn();
2186
+ runner.stop();
2187
+ });
2188
+ register(node, () => runner.stop());
2189
+ return;
2190
+ }
2191
+ autoEffect(node, fn);
2192
+ }
2193
+ function compileNode(node, ctx) {
2194
+ if (!isElement(node)) return;
2195
+ const IF_ATTRS = ["sky-if", "v-if", "w-if"];
2196
+ const ELSEIF_ATTRS = ["sky-else-if", "v-else-if", "w-else-if"];
2197
+ const ELSE_ATTRS = ["sky-else", "v-else", "w-else"];
2198
+ const hasAnyAttr = (el, names) => names.some((n) => el.hasAttribute(n));
2199
+ const getAnyAttr = (el, names) => {
2200
+ for (const n of names)
2201
+ if (el.hasAttribute(n)) return el.getAttribute(n) || "";
2202
+ return "";
2203
+ };
2204
+ const removeAnyAttr = (el, names) => names.forEach((n) => el.removeAttribute(n));
2205
+ const nextUsefulSibling = (n) => {
2206
+ let cur = n;
2207
+ while (cur) {
2208
+ if (cur.nodeType === 8) {
2209
+ cur = cur.nextSibling;
2210
+ continue;
2211
+ }
2212
+ if (cur.nodeType === 3 && !(cur.nodeValue ?? "").trim()) {
2213
+ cur = cur.nextSibling;
2214
+ continue;
2215
+ }
2216
+ return cur;
2217
+ }
2218
+ return null;
2219
+ };
2220
+ if (hasAnyAttr(node, IF_ATTRS)) {
2221
+ const parent = node.parentNode;
2222
+ if (!parent) return;
2223
+ const anchor = createComment(node, "if-chain");
2224
+ parent.insertBefore(anchor, node);
2225
+ const chain = [];
2226
+ let cur = node;
2227
+ while (cur) {
2228
+ cur = nextUsefulSibling(cur);
2229
+ if (!cur || cur.nodeType !== 1) break;
2230
+ const elCur = cur;
2231
+ const isIf = hasAnyAttr(elCur, IF_ATTRS);
2232
+ const isElseIf = hasAnyAttr(elCur, ELSEIF_ATTRS);
2233
+ const isElse = hasAnyAttr(elCur, ELSE_ATTRS);
2234
+ if (!isIf && !isElseIf && !isElse) break;
2235
+ if (chain.length > 0 && isIf) break;
2236
+ if (chain.length === 0 && !isIf) break;
2237
+ if (chain.length > 0 && chain[chain.length - 1].isElse) break;
2238
+ const expStr = isElse ? "" : getAnyAttr(elCur, IF_ATTRS) || getAnyAttr(elCur, ELSEIF_ATTRS);
2239
+ const expAst = expStr ? compileExpr(expStr) : null;
2240
+ const tpl = elCur.cloneNode(true);
2241
+ if (isElement(tpl)) {
2242
+ removeAnyAttr(tpl, IF_ATTRS);
2243
+ removeAnyAttr(tpl, ELSEIF_ATTRS);
2244
+ removeAnyAttr(tpl, ELSE_ATTRS);
2245
+ }
2246
+ chain.push({ isElse: !!isElse, expAst, tpl });
2247
+ const next = elCur.nextSibling;
2248
+ elCur.remove();
2249
+ cur = next;
2250
+ }
2251
+ let activeEl = null;
2252
+ bindReactive(anchor, () => {
2253
+ let matched = false;
2254
+ for (const item of chain) {
2255
+ const ok = !matched && (item.isElse || item.expAst != null && !!evalInCtxAst(item.expAst, ctx, void 0, anchor, "if"));
2256
+ if (!ok) continue;
2257
+ matched = true;
2258
+ if (!activeEl || activeEl.__skyIfTpl !== item.tpl) {
2259
+ if (activeEl) {
2260
+ cleanup(activeEl);
2261
+ activeEl.remove();
2262
+ activeEl = null;
2263
+ }
2264
+ const el = item.tpl.cloneNode(true);
2265
+ el.__skyIfTpl = item.tpl;
2266
+ parent.insertBefore(el, anchor.nextSibling);
2267
+ compileTree(el, ctx);
2268
+ activeEl = el;
2269
+ }
2270
+ break;
2271
+ }
2272
+ if (!matched && activeEl) {
2273
+ cleanup(activeEl);
2274
+ activeEl.remove();
2275
+ activeEl = null;
2276
+ }
2277
+ });
2278
+ return;
2279
+ }
2280
+ if (node.hasAttribute("sky-for")) {
2281
+ const exp = node.getAttribute("sky-for") || "";
2282
+ const keyExp = node.getAttribute("sky-key");
2283
+ const parts = exp.split(/\s+in\s+/);
2284
+ const lhs = parts[0] || "";
2285
+ const rhs = parts.slice(1).join(" in ") || "";
2286
+ let alias;
2287
+ let indexAlias;
2288
+ try {
2289
+ ({ item: alias, index: indexAlias } = parseForAlias(lhs));
2290
+ } catch {
2291
+ warn(
2292
+ WarnCodes.FOR_INVALID_SYNTAX,
2293
+ { expr: exp },
2294
+ { element: node, label: "sky-for" }
2295
+ );
2296
+ return;
2297
+ }
2298
+ const listAst = compileExpr(rhs.trim());
2299
+ const keyAst = keyExp ? compileExpr(keyExp) : null;
2300
+ if (!keyAst && getCompileMode() !== "ssr") {
2301
+ warnOnce(WarnCodes.FOR_KEY_RECOMMENDED, {}, { element: node, label: "sky-for" });
2302
+ }
2303
+ const parent = node.parentNode;
2304
+ if (!parent) return;
2305
+ const anchor = createComment(node, "sky-for");
2306
+ parent.replaceChild(anchor, node);
2307
+ const template = node.cloneNode(true);
2308
+ template.removeAttribute("sky-for");
2309
+ template.removeAttribute("sky-key");
2310
+ const blocks = /* @__PURE__ */ new Map();
2311
+ const runList = () => {
2312
+ const sourceValue = evalInCtxAst(listAst, ctx, void 0, anchor, "for");
2313
+ const items = normalizeForSource(sourceValue, indexAlias);
2314
+ const used = /* @__PURE__ */ new Set();
2315
+ const listParent = anchor.parentNode;
2316
+ if (!listParent) return;
2317
+ let insertBefore = anchor.nextSibling;
2318
+ for (let idx = 0; idx < items.length; idx++) {
2319
+ const item = items[idx];
2320
+ if (!item) continue;
2321
+ const itemValue = item.value;
2322
+ const extra = item.extra;
2323
+ let blockKey;
2324
+ if (keyAst) {
2325
+ const keyCtx = Object.create(ctx);
2326
+ keyCtx[alias] = itemValue;
2327
+ keyCtx.$item = itemValue;
2328
+ keyCtx.$index = idx;
2329
+ if (indexAlias) keyCtx[indexAlias] = idx;
2330
+ Object.assign(keyCtx, extra);
2331
+ blockKey = evalInCtxAst(keyAst, keyCtx, void 0, anchor, "for:key");
2332
+ } else {
2333
+ blockKey = item.key;
2334
+ }
2335
+ let block = blocks.get(blockKey);
2336
+ if (!block) {
2337
+ const el = template.cloneNode(true);
2338
+ const rowCtx = Object.create(ctx);
2339
+ rowCtx[alias] = itemValue;
2340
+ rowCtx.$item = itemValue;
2341
+ rowCtx.$index = idx;
2342
+ if (indexAlias) rowCtx[indexAlias] = idx;
2343
+ Object.assign(rowCtx, extra);
2344
+ compileTree(el, rowCtx);
2345
+ block = { el, ctx: rowCtx };
2346
+ blocks.set(blockKey, block);
2347
+ } else {
2348
+ block.ctx[alias] = itemValue;
2349
+ block.ctx.$item = itemValue;
2350
+ block.ctx.$index = idx;
2351
+ if (indexAlias) block.ctx[indexAlias] = idx;
2352
+ Object.assign(block.ctx, extra);
2353
+ }
2354
+ if (block.el.parentNode !== listParent || block.el.nextSibling !== insertBefore) {
2355
+ listParent.insertBefore(block.el, insertBefore);
2356
+ }
2357
+ insertBefore = block.el.nextSibling;
2358
+ used.add(blockKey);
2359
+ }
2360
+ blocks.forEach((block, k) => {
2361
+ if (!used.has(k)) {
2362
+ if (getCompileMode() !== "ssr") cleanup(block.el);
2363
+ block.el.parentNode?.removeChild(block.el);
2364
+ blocks.delete(k);
2365
+ }
2366
+ });
2367
+ };
2368
+ if (getCompileMode() === "ssr") {
2369
+ runList();
2370
+ } else {
2371
+ autoEffect(anchor, runList);
2372
+ }
2373
+ return;
2374
+ }
2375
+ if (node.hasAttribute("sky-ref")) {
2376
+ const k = node.getAttribute("sky-ref");
2377
+ if (!k) return;
2378
+ node.removeAttribute("sky-ref");
2379
+ const slot = ctx[k];
2380
+ if (isRef(slot)) slot.value = node;
2381
+ else ctx[k] = ref(node);
2382
+ register(node, () => {
2383
+ const cur = ctx[k];
2384
+ if (isRef(cur)) cur.value = null;
2385
+ });
2386
+ }
2387
+ if (node.hasAttribute("sky-show")) {
2388
+ const exp = node.getAttribute("sky-show") || "";
2389
+ node.removeAttribute("sky-show");
2390
+ const expAst = compileExpr(exp);
2391
+ const html = asHtmlEl(node);
2392
+ bindReactive(node, () => {
2393
+ html.style.display = evalInCtxAst(expAst, ctx, void 0, node, "show") ? "" : "none";
2394
+ });
2395
+ }
2396
+ if (node.hasAttribute("sky-html")) {
2397
+ warnOnce(WarnCodes.SKY_HTML_UNSAFE, {}, { element: node, label: "sky-html" });
2398
+ const exp = node.getAttribute("sky-html") || "";
2399
+ node.removeAttribute("sky-html");
2400
+ const expAst = compileExpr(exp);
2401
+ const htmlEl = asHtmlEl(node);
2402
+ bindReactive(node, () => {
2403
+ const val = evalInCtxAst(expAst, ctx, void 0, node, "html");
2404
+ htmlEl.innerHTML = val == null ? "" : String(val);
2405
+ });
2406
+ }
2407
+ const attrs = Array.from(node.attributes);
2408
+ const modelAttrs = attrs.filter((a) => isSkyModelAttr(a.name));
2409
+ if (modelAttrs.length > 1) {
2410
+ warnOnce(WarnCodes.MODEL_DUPLICATE, {}, { element: node });
2411
+ }
2412
+ const modelAttr = modelAttrs[0];
2413
+ if (modelAttr) {
2414
+ const binding = parseSkyModelAttr(modelAttr.name, modelAttr.value);
2415
+ if (!binding) {
2416
+ warn(
2417
+ WarnCodes.MODEL_INVALID_KEY,
2418
+ { value: modelAttr.value },
2419
+ { element: node, label: modelAttr.name }
2420
+ );
2421
+ } else {
2422
+ node.removeAttribute(modelAttr.name);
2423
+ const { key, arg, modifiers, unknownModifiers } = binding;
2424
+ if (unknownModifiers.length > 0) {
2425
+ warnOnce(
2426
+ WarnCodes.MODEL_UNKNOWN_MODIFIER,
2427
+ { mods: unknownModifiers.join(".") },
2428
+ { element: node, label: modelAttr.name }
2429
+ );
2430
+ }
2431
+ if (isCustomElement(node)) {
2432
+ const custom = bindCustomSkyModel(node, ctx, key, arg, modifiers);
2433
+ bindReactive(node, () => custom.read());
2434
+ node.addEventListener(custom.eventName, custom.onUpdate);
2435
+ register(
2436
+ node,
2437
+ () => node.removeEventListener(custom.eventName, custom.onUpdate)
2438
+ );
2439
+ } else {
2440
+ if (arg != null) {
2441
+ warn(
2442
+ WarnCodes.MODEL_ARG_ON_NATIVE,
2443
+ { arg, tag: node.tagName.toLowerCase(), key },
2444
+ { element: node, label: modelAttr.name }
2445
+ );
2446
+ }
2447
+ const model = bindSkyModel(node, ctx, key, modifiers);
2448
+ bindReactive(node, () => model.read());
2449
+ const h = () => writeModelValue(ctx, key, node, readModelValue(node), modifiers);
2450
+ node.addEventListener(model.event, h);
2451
+ register(node, () => node.removeEventListener(model.event, h));
2452
+ }
2453
+ }
2454
+ }
2455
+ const isOnAttr = (name) => name.startsWith("on") && name.length > 2;
2456
+ for (const a of attrs) {
2457
+ const attrName = a.name;
2458
+ const code = a.value;
2459
+ if (isOnAttr(attrName)) {
2460
+ const binding = parseOnEventAttr(attrName);
2461
+ if (!binding) continue;
2462
+ node.removeAttribute(attrName);
2463
+ warnUnknownEventModifiers(node, binding, `on${binding.event}`);
2464
+ const opts = getListenerOptions(binding.modifiers);
2465
+ const handler = wrapEventHandler(
2466
+ (e) => runHandler(code, ctx, node, `on${binding.event}`, e),
2467
+ binding.modifiers,
2468
+ node
2469
+ );
2470
+ node.addEventListener(binding.event, handler, opts);
2471
+ register(node, () => node.removeEventListener(binding.event, handler, opts));
2472
+ continue;
2473
+ }
2474
+ if (attrName.startsWith("@")) {
2475
+ const binding = parseAtEventAttr(attrName, code);
2476
+ if (!binding) continue;
2477
+ node.removeAttribute(attrName);
2478
+ warnUnknownEventModifiers(node, binding, `@${binding.event}`);
2479
+ const opts = getListenerOptions(binding.modifiers);
2480
+ const handler = wrapEventHandler(
2481
+ (e) => runHandler(code, ctx, node, `@${binding.event}`, e),
2482
+ binding.modifiers,
2483
+ node
2484
+ );
2485
+ node.addEventListener(binding.event, handler, opts);
2486
+ register(node, () => node.removeEventListener(binding.event, handler, opts));
2487
+ continue;
2488
+ }
2489
+ if (attrName === ":class" || attrName === "sky-bind:class") {
2490
+ node.removeAttribute(attrName);
2491
+ const expAst = compileExpr(code);
2492
+ const html = asHtmlEl(node);
2493
+ const base = html.dataset.baseClass ?? (html.dataset.baseClass = html.className);
2494
+ bindReactive(node, () => {
2495
+ const val = evalInCtxAst(expAst, ctx, void 0, node, "class");
2496
+ const cls = normalizeClass(val);
2497
+ html.className = base + (cls ? " " + cls : "");
2498
+ });
2499
+ continue;
2500
+ }
2501
+ if (attrName === ":style" || attrName === "sky-bind:style") {
2502
+ node.removeAttribute(attrName);
2503
+ const expAst = compileExpr(code);
2504
+ const html = asHtmlEl(node);
2505
+ bindReactive(node, () => {
2506
+ const val = normalizeStyle(
2507
+ evalInCtxAst(expAst, ctx, void 0, node, "style")
2508
+ );
2509
+ if (typeof val === "string") html.style.cssText = val;
2510
+ else {
2511
+ const styleObj = val;
2512
+ for (const k of Object.keys(styleObj)) {
2513
+ html.style.setProperty(k, String(styleObj[k]));
2514
+ }
2515
+ }
2516
+ });
2517
+ continue;
2518
+ }
2519
+ if (attrName.startsWith("sky-bind:") && attrName !== "sky-bind:class" && attrName !== "sky-bind:style") {
2520
+ node.removeAttribute(attrName);
2521
+ let prop = attrName.split(":")[1] ?? "";
2522
+ prop = resolveDomPropName(node, prop);
2523
+ const expAst = compileExpr(code);
2524
+ if (prop === "value" && isTextInputLike(node)) {
2525
+ bindReactive(node, () => {
2526
+ const v = evalInCtxAst(expAst, ctx, void 0, node, "bind:value");
2527
+ const str = v == null ? "" : String(v);
2528
+ if (typeof document !== "undefined" && document.activeElement === node)
2529
+ return;
2530
+ if (node.value !== str) node.value = str;
2531
+ });
2532
+ } else {
2533
+ bindReactive(node, () => {
2534
+ let v = evalInCtxAst(expAst, ctx, void 0, node, `bind:${prop}`);
2535
+ if (isCustomElement(node) && (Array.isArray(v) || v && typeof v === "object")) {
2536
+ deepTrack(v);
2537
+ v = cloneShallow(v);
2538
+ }
2539
+ node[prop] = v;
2540
+ });
2541
+ }
2542
+ continue;
2543
+ }
2544
+ }
2545
+ compileChildren(node, ctx);
2546
+ }
2547
+ function compileTree(root, ctx) {
2548
+ if (isElement(root)) {
2549
+ compileNode(root, ctx);
2550
+ return;
2551
+ }
2552
+ compileChildren(root, ctx);
2553
+ }
2554
+
2555
+ // src/runtime/mount.ts
2556
+ function mount(root, ctx) {
2557
+ compileTree(root, ctx);
2558
+ return ctx;
2559
+ }
2560
+
2561
+ // src/runtime/context.ts
2562
+ function createCtx(exposed = {}) {
2563
+ const ctx = reactive({});
2564
+ if (exposed && typeof exposed === "object") Object.assign(ctx, exposed);
2565
+ return ctx;
2566
+ }
2567
+
2568
+ // src/runtime/app.ts
2569
+ function createReactivity(setup) {
2570
+ return {
2571
+ mount(target, initial = {}) {
2572
+ const root = typeof target === "string" ? document.querySelector(target) : target;
2573
+ if (!root) {
2574
+ const targetLabel = typeof target === "string" ? target : "<element>";
2575
+ warn(WarnCodes.MOUNT_TARGET_NOT_FOUND, { target: targetLabel });
2576
+ throw new Error(getWarnMessage(WarnCodes.MOUNT_TARGET_NOT_FOUND, { target: targetLabel }));
2577
+ }
2578
+ const scope = effectScope(true);
2579
+ return scope.run(() => {
2580
+ const exposed = (typeof setup === "function" ? setup() : setup) || {};
2581
+ const ctx = createCtx({ ...initial, ...exposed });
2582
+ mount(root, ctx);
2583
+ return {
2584
+ ctx,
2585
+ unmount() {
2586
+ cleanup(root);
2587
+ scope.stop();
2588
+ clearAstCaches();
2589
+ }
2590
+ };
2591
+ });
2592
+ }
2593
+ };
2594
+ }
2595
+
2596
+ // src/ssr/document.ts
2597
+ async function parseSSRDocument(markup) {
2598
+ if (typeof DOMParser !== "undefined") {
2599
+ const doc = new DOMParser().parseFromString(markup, "text/html");
2600
+ return doc;
2601
+ }
2602
+ try {
2603
+ const { parseHTML } = await import('linkedom');
2604
+ const { document: document2 } = parseHTML(markup);
2605
+ return document2;
2606
+ } catch {
2607
+ throw new Error(
2608
+ "[Sky SSR] No DOM available. Use in a browser or install optional peer `linkedom`."
2609
+ );
2610
+ }
2611
+ }
2612
+
2613
+ // src/ssr/strip-anchors.ts
2614
+ var ANCHOR_MARKERS = /* @__PURE__ */ new Set(["sky-for", "if-chain"]);
2615
+ function stripCompilerCommentAnchors(root) {
2616
+ const comments = [];
2617
+ const walk = (node) => {
2618
+ for (const child of Array.from(node.childNodes)) {
2619
+ if (child.nodeType === 8) {
2620
+ const data = child.data.trim();
2621
+ if (ANCHOR_MARKERS.has(data)) comments.push(child);
2622
+ } else if (child.nodeType === 1) {
2623
+ walk(child);
2624
+ }
2625
+ }
2626
+ };
2627
+ walk(root);
2628
+ for (const c of comments) {
2629
+ c.parentNode?.removeChild(c);
2630
+ }
2631
+ }
2632
+
2633
+ // src/ssr/render.ts
2634
+ async function renderToString(markup, ctx, options = {}) {
2635
+ const doc = await parseSSRDocument(markup);
2636
+ const root = options.root != null ? doc.querySelector(options.root) : doc.body;
2637
+ if (!root) {
2638
+ const rootSel = options.root ?? "body";
2639
+ warn(WarnCodes.SSR_ROOT_NOT_FOUND, { root: rootSel });
2640
+ throw new Error(getWarnMessage(WarnCodes.SSR_ROOT_NOT_FOUND, { root: rootSel }));
2641
+ }
2642
+ const scope = { ...options.initial, ...ctx };
2643
+ const reactiveCtx = createCtx(scope);
2644
+ runInCompileMode("ssr", () => {
2645
+ compileTree(root, reactiveCtx);
2646
+ });
2647
+ const stripAnchors = options.stripAnchors !== false;
2648
+ if (stripAnchors) {
2649
+ stripCompilerCommentAnchors(root);
2650
+ if (options.fullDocument && doc.documentElement) {
2651
+ stripCompilerCommentAnchors(doc.documentElement);
2652
+ }
2653
+ }
2654
+ if (options.fullDocument) {
2655
+ return doc.documentElement.outerHTML;
2656
+ }
2657
+ return root.nodeType === 1 ? root.outerHTML : String(root);
2658
+ }
2659
+
2660
+ // src/runtime/handler-runner.ts
2661
+ async function runHandlerCode(code, ctx, $event = null, $el = null) {
2662
+ const program = compileStmt(code);
2663
+ if (/\bawait\b/.test(code)) {
2664
+ return runInCtxAstAsync(program, ctx, $event, $el, "handler");
2665
+ }
2666
+ return runInCtxAst(program, ctx, $event, $el, "handler");
2667
+ }
2668
+
2669
+ export { EffectScope, WarnCodes, skyDevSnapshot as __SKY_DEV__, computed, createReactivity, customRef, effect, effectScope, flushSync, getCurrentScope, getSkyDev, isReactive, isReadonly, isRef, logError, markRaw, mount, nextTick, onScopeDispose, parseSSRDocument, reactive, readonly, ref, renderToString, resetWarned, runHandlerCode, setSkyDev, setWarnHandler, shallowReactive, shallowReadonly, shallowRef, toRaw, toRef, toRefs, triggerRef, unref, warn, warnOnce, watch, watchEffect };
2670
+ //# sourceMappingURL=index.js.map
2671
+ //# sourceMappingURL=index.js.map