olova 2.0.64 → 2.0.68
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/CHANGELOG.md +5 -5
- package/README.md +42 -42
- package/dist/compiler.d.ts +76 -1
- package/dist/compiler.js +13204 -629
- package/dist/compiler.js.map +1 -1
- package/dist/core.d.ts +2 -2
- package/dist/core.js +400 -38
- package/dist/core.js.map +1 -1
- package/dist/global.d.ts +1 -1
- package/dist/global.js +54 -8
- package/dist/global.js.map +1 -1
- package/dist/index.js +13178 -639
- package/dist/index.js.map +1 -1
- package/dist/runtime.d.ts +8 -3
- package/dist/runtime.js +512 -32
- package/dist/runtime.js.map +1 -1
- package/dist/{signals-core-BdfWh1Yt.d.ts → signals-core-BWZ5zXK5.d.ts} +6 -5
- package/dist/vite.js +13178 -639
- package/dist/vite.js.map +1 -1
- package/package.json +83 -83
package/dist/core.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { E as EffectCallback, a as EffectCleanup,
|
|
2
|
-
export { CompiledDescriptor, DangerousHtml, OlovaComponent, OlovaProps, OlovaSlots, SetupFn, createApp, dangerouslySetHtml, defineComponent, getContext, hasContext, mount, replaceComponent, setContext } from './runtime.js';
|
|
1
|
+
export { E as EffectCallback, a as EffectCleanup, R as RuntimeErrorHandler, S as Signal, b as SignalState, c as beginHmrStateCapture, d as computed, e as derived, f as effect, g as endHmrStateCapture, h as getReactiveProxyVersion, s as state, w as withRuntimeErrorHandler } from './signals-core-BWZ5zXK5.js';
|
|
2
|
+
export { CompiledDescriptor, DangerousHtml, ErrorBoundaryFallback, OlovaComponent, OlovaProps, OlovaSlots, SetupFn, Suspense, createApp, createErrorBoundary, dangerouslySetHtml, defineComponent, getContext, hasContext, mount, onCleanup, onMount, replaceComponent, setContext } from './runtime.js';
|
|
3
3
|
export { global } from './global.js';
|
|
4
4
|
import '@preact/signals-core';
|
package/dist/core.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { signal, effect as effect$1, computed as computed$1, untracked } from '@preact/signals-core';
|
|
2
2
|
|
|
3
3
|
// core/signals-core.ts
|
|
4
|
-
var
|
|
4
|
+
var rawToProxyByOwner = /* @__PURE__ */ new WeakMap();
|
|
5
5
|
var proxyToRaw = /* @__PURE__ */ new WeakMap();
|
|
6
6
|
var proxyOwner = /* @__PURE__ */ new WeakMap();
|
|
7
7
|
var hmrCaptureStack = [];
|
|
8
|
+
var runtimeErrorHandlerStack = [];
|
|
8
9
|
function isObject(value) {
|
|
9
10
|
return typeof value === "object" && value !== null;
|
|
10
11
|
}
|
|
@@ -40,6 +41,9 @@ var Signal = class {
|
|
|
40
41
|
notify() {
|
|
41
42
|
this.version.value = this.version.peek() + 1;
|
|
42
43
|
}
|
|
44
|
+
peekVersion() {
|
|
45
|
+
return this.version.peek();
|
|
46
|
+
}
|
|
43
47
|
subscribe(fn) {
|
|
44
48
|
return this.source.subscribe(fn);
|
|
45
49
|
}
|
|
@@ -63,7 +67,8 @@ var Signal = class {
|
|
|
63
67
|
return this.proxy;
|
|
64
68
|
}
|
|
65
69
|
wrapObject(value) {
|
|
66
|
-
const
|
|
70
|
+
const ownedProxyMap = rawToProxyByOwner.get(value);
|
|
71
|
+
const existing = ownedProxyMap?.get(this);
|
|
67
72
|
if (existing) {
|
|
68
73
|
return existing;
|
|
69
74
|
}
|
|
@@ -90,7 +95,11 @@ var Signal = class {
|
|
|
90
95
|
return changed;
|
|
91
96
|
}
|
|
92
97
|
});
|
|
93
|
-
|
|
98
|
+
const nextOwnedProxyMap = ownedProxyMap ?? /* @__PURE__ */ new WeakMap();
|
|
99
|
+
nextOwnedProxyMap.set(this, proxy);
|
|
100
|
+
if (!ownedProxyMap) {
|
|
101
|
+
rawToProxyByOwner.set(value, nextOwnedProxyMap);
|
|
102
|
+
}
|
|
94
103
|
proxyToRaw.set(proxy, value);
|
|
95
104
|
proxyOwner.set(proxy, this);
|
|
96
105
|
return proxy;
|
|
@@ -122,15 +131,59 @@ function state(initial, hmrKey) {
|
|
|
122
131
|
}
|
|
123
132
|
return signal;
|
|
124
133
|
}
|
|
125
|
-
function
|
|
126
|
-
|
|
134
|
+
function getReactiveProxyVersion(value) {
|
|
135
|
+
if (!isObject(value)) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
const owner = proxyOwner.get(value);
|
|
139
|
+
return owner ? owner.peekVersion() : null;
|
|
140
|
+
}
|
|
141
|
+
function reportRuntimeError(error, handler) {
|
|
142
|
+
if (handler) {
|
|
143
|
+
handler(error);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
throw error;
|
|
147
|
+
}
|
|
148
|
+
function withRuntimeErrorHandler(handler, fn) {
|
|
149
|
+
if (!handler) {
|
|
150
|
+
return fn();
|
|
151
|
+
}
|
|
152
|
+
runtimeErrorHandlerStack.push(handler);
|
|
153
|
+
try {
|
|
154
|
+
return fn();
|
|
155
|
+
} finally {
|
|
156
|
+
runtimeErrorHandlerStack.pop();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function effect(fn) {
|
|
160
|
+
const handler = runtimeErrorHandlerStack[runtimeErrorHandlerStack.length - 1] ?? null;
|
|
161
|
+
const stop = effect$1(
|
|
162
|
+
() => withRuntimeErrorHandler(handler, () => {
|
|
163
|
+
try {
|
|
164
|
+
const cleanup = fn();
|
|
165
|
+
if (typeof cleanup !== "function") {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
return () => withRuntimeErrorHandler(handler, () => {
|
|
169
|
+
try {
|
|
170
|
+
cleanup();
|
|
171
|
+
} catch (error) {
|
|
172
|
+
reportRuntimeError(error, handler);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
} catch (error) {
|
|
176
|
+
reportRuntimeError(error, handler);
|
|
177
|
+
}
|
|
178
|
+
})
|
|
179
|
+
);
|
|
127
180
|
return () => stop();
|
|
128
181
|
}
|
|
129
182
|
function computed(getter) {
|
|
130
183
|
const version = signal(0);
|
|
131
184
|
const source = computed$1(() => getter());
|
|
132
185
|
effect$1(() => {
|
|
133
|
-
|
|
186
|
+
source.value;
|
|
134
187
|
version.value = version.peek() + 1;
|
|
135
188
|
});
|
|
136
189
|
return new Signal(untracked(() => source.value), source, version);
|
|
@@ -162,6 +215,40 @@ function endHmrStateCapture() {
|
|
|
162
215
|
// runtime/component.ts
|
|
163
216
|
var EMPTY_SLOTS = Object.freeze({});
|
|
164
217
|
var currentSetupContext = null;
|
|
218
|
+
var currentLifecycleHooks = null;
|
|
219
|
+
var ERROR_BOUNDARY = /* @__PURE__ */ Symbol("olova.error-boundary");
|
|
220
|
+
var SUSPENSE_BOUNDARY = /* @__PURE__ */ Symbol("olova.suspense-boundary");
|
|
221
|
+
function isPromiseLike(value) {
|
|
222
|
+
return !!value && typeof value === "object" && "then" in value;
|
|
223
|
+
}
|
|
224
|
+
function toOlovaError(error, context) {
|
|
225
|
+
if (error instanceof Error && error.message.startsWith("[olova]")) {
|
|
226
|
+
return error;
|
|
227
|
+
}
|
|
228
|
+
const original = error instanceof Error ? error : new Error(String(error));
|
|
229
|
+
const wrapped = new Error(`[olova] ${context}: ${original.message}`);
|
|
230
|
+
wrapped.cause = error;
|
|
231
|
+
return wrapped;
|
|
232
|
+
}
|
|
233
|
+
function getBoundaryHandler(context) {
|
|
234
|
+
return context?.get(ERROR_BOUNDARY) ?? null;
|
|
235
|
+
}
|
|
236
|
+
function handleRuntimeError(error, contextMessage, context) {
|
|
237
|
+
const normalized = toOlovaError(error, contextMessage);
|
|
238
|
+
const boundaryHandler = getBoundaryHandler(context);
|
|
239
|
+
if (boundaryHandler) {
|
|
240
|
+
boundaryHandler(normalized);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
throw normalized;
|
|
244
|
+
}
|
|
245
|
+
function runWithRuntimeErrorHandler(context, action, fn) {
|
|
246
|
+
try {
|
|
247
|
+
return withRuntimeErrorHandler(getBoundaryHandler(context), fn);
|
|
248
|
+
} catch (error) {
|
|
249
|
+
return handleRuntimeError(error, action, context);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
165
252
|
function requireSetupContext(apiName) {
|
|
166
253
|
if (!currentSetupContext) {
|
|
167
254
|
throw new Error(
|
|
@@ -220,12 +307,12 @@ function sanitizeHtml(html) {
|
|
|
220
307
|
}
|
|
221
308
|
for (const attr of Array.from(element.attributes)) {
|
|
222
309
|
const attrName = attr.name.toLowerCase();
|
|
223
|
-
const attrValue = attr.value.trim()
|
|
310
|
+
const attrValue = attr.value.trim();
|
|
224
311
|
if (attrName.startsWith("on")) {
|
|
225
312
|
element.removeAttribute(attr.name);
|
|
226
313
|
continue;
|
|
227
314
|
}
|
|
228
|
-
if ((attrName === "href" || attrName === "src" || attrName === "xlink:href") && attrValue
|
|
315
|
+
if ((attrName === "href" || attrName === "src" || attrName === "xlink:href") && !isSafeUrl(attrName, attrValue)) {
|
|
229
316
|
element.removeAttribute(attr.name);
|
|
230
317
|
}
|
|
231
318
|
}
|
|
@@ -244,7 +331,27 @@ function toHtml(value) {
|
|
|
244
331
|
}
|
|
245
332
|
return sanitizeHtml(String(value));
|
|
246
333
|
}
|
|
247
|
-
|
|
334
|
+
var SAFE_URL_PROTOCOLS = /* @__PURE__ */ new Set(["http", "https", "mailto", "tel"]);
|
|
335
|
+
var SAFE_IMAGE_DATA_URL_RE = /^data:image\/(?:png|gif|jpe?g|webp|avif|bmp);(?:charset=[^;,]+;)?base64,[a-z0-9+/=\s]+$/i;
|
|
336
|
+
function isSafeUrl(attrName, value) {
|
|
337
|
+
const normalized = value.replace(/[\u0000-\u001F\u007F\s]+/g, "");
|
|
338
|
+
if (!normalized) {
|
|
339
|
+
return true;
|
|
340
|
+
}
|
|
341
|
+
if (normalized.startsWith("#") || normalized.startsWith("/") || normalized.startsWith("./") || normalized.startsWith("../") || normalized.startsWith("?")) {
|
|
342
|
+
return true;
|
|
343
|
+
}
|
|
344
|
+
const match = normalized.match(/^([a-z0-9+.-]+):/i);
|
|
345
|
+
if (!match) {
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
const protocol = match[1].toLowerCase();
|
|
349
|
+
if (SAFE_URL_PROTOCOLS.has(protocol)) {
|
|
350
|
+
return true;
|
|
351
|
+
}
|
|
352
|
+
return protocol === "data" && attrName === "src" && SAFE_IMAGE_DATA_URL_RE.test(normalized);
|
|
353
|
+
}
|
|
354
|
+
function shallowEqualSlots(a, b) {
|
|
248
355
|
if (a === b) {
|
|
249
356
|
return true;
|
|
250
357
|
}
|
|
@@ -263,20 +370,39 @@ function shallowEqual(a, b) {
|
|
|
263
370
|
}
|
|
264
371
|
return true;
|
|
265
372
|
}
|
|
266
|
-
function
|
|
267
|
-
|
|
373
|
+
function createComparablePropsSnapshot(props) {
|
|
374
|
+
return Object.fromEntries(
|
|
375
|
+
Object.entries(props).map(([key, value]) => [
|
|
376
|
+
key,
|
|
377
|
+
{
|
|
378
|
+
value,
|
|
379
|
+
reactiveVersion: getReactiveProxyVersion(value)
|
|
380
|
+
}
|
|
381
|
+
])
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
function shallowComparablePropsEqual(snapshot, props) {
|
|
385
|
+
if (!snapshot && !props) {
|
|
268
386
|
return true;
|
|
269
387
|
}
|
|
270
|
-
if (!
|
|
388
|
+
if (!snapshot || !props) {
|
|
271
389
|
return false;
|
|
272
390
|
}
|
|
273
|
-
const
|
|
274
|
-
const
|
|
275
|
-
if (
|
|
391
|
+
const keys = Object.keys(snapshot);
|
|
392
|
+
const propKeys = Object.keys(props);
|
|
393
|
+
if (keys.length !== propKeys.length) {
|
|
276
394
|
return false;
|
|
277
395
|
}
|
|
278
|
-
for (const key of
|
|
279
|
-
if (!
|
|
396
|
+
for (const key of keys) {
|
|
397
|
+
if (!(key in props)) {
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
const entry = snapshot[key];
|
|
401
|
+
const nextValue = props[key];
|
|
402
|
+
if (!Object.is(entry.value, nextValue)) {
|
|
403
|
+
return false;
|
|
404
|
+
}
|
|
405
|
+
if (entry.reactiveVersion !== getReactiveProxyVersion(nextValue)) {
|
|
280
406
|
return false;
|
|
281
407
|
}
|
|
282
408
|
}
|
|
@@ -309,7 +435,7 @@ function bindJsxEventsInRange(range) {
|
|
|
309
435
|
const listeners = [];
|
|
310
436
|
const handlerIds = /* @__PURE__ */ new Set();
|
|
311
437
|
const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
|
|
312
|
-
let current = walker.
|
|
438
|
+
let current = walker.nextNode();
|
|
313
439
|
while (current) {
|
|
314
440
|
let intersects = false;
|
|
315
441
|
try {
|
|
@@ -429,6 +555,42 @@ function createRangeAtTokenWithinRange(hostRange, token) {
|
|
|
429
555
|
function resolveTokenRange(target, token) {
|
|
430
556
|
return target instanceof HTMLElement ? createRangeAtToken(target, token) : createRangeAtTokenWithinRange(target, token);
|
|
431
557
|
}
|
|
558
|
+
function createLifecycleHooks() {
|
|
559
|
+
return {
|
|
560
|
+
mount: [],
|
|
561
|
+
cleanup: []
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
function flushLifecycleHooks(hooks, context) {
|
|
565
|
+
for (const mountHook of hooks.mount) {
|
|
566
|
+
const cleanup = runWithRuntimeErrorHandler(
|
|
567
|
+
context,
|
|
568
|
+
"Failed to run onMount() callback",
|
|
569
|
+
mountHook
|
|
570
|
+
);
|
|
571
|
+
if (typeof cleanup === "function") {
|
|
572
|
+
hooks.cleanup.push(cleanup);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
return () => {
|
|
576
|
+
for (let index = hooks.cleanup.length - 1; index >= 0; index -= 1) {
|
|
577
|
+
runWithRuntimeErrorHandler(
|
|
578
|
+
context,
|
|
579
|
+
"Failed to run cleanup callback",
|
|
580
|
+
hooks.cleanup[index]
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
function createDescriptorEffect(context, fn) {
|
|
586
|
+
const stop = runWithRuntimeErrorHandler(
|
|
587
|
+
context,
|
|
588
|
+
"Failed to create reactive binding",
|
|
589
|
+
() => effect(fn)
|
|
590
|
+
);
|
|
591
|
+
return typeof stop === "function" ? stop : () => {
|
|
592
|
+
};
|
|
593
|
+
}
|
|
432
594
|
function mountDescriptor(descriptor, target, slots, context) {
|
|
433
595
|
let fragment;
|
|
434
596
|
let nodes = null;
|
|
@@ -448,7 +610,7 @@ function mountDescriptor(descriptor, target, slots, context) {
|
|
|
448
610
|
if (!textNode) {
|
|
449
611
|
continue;
|
|
450
612
|
}
|
|
451
|
-
const stop =
|
|
613
|
+
const stop = createDescriptorEffect(context, () => {
|
|
452
614
|
textNode.data = toText(binding.get());
|
|
453
615
|
});
|
|
454
616
|
cleanups.push(stop);
|
|
@@ -459,7 +621,7 @@ function mountDescriptor(descriptor, target, slots, context) {
|
|
|
459
621
|
(element) => element.getAttribute(binding.attr) === token
|
|
460
622
|
);
|
|
461
623
|
for (const element of elements) {
|
|
462
|
-
const stop =
|
|
624
|
+
const stop = createDescriptorEffect(context, () => {
|
|
463
625
|
const next = binding.attr === "class" ? normalizeClassValue(binding.get()) : toAttr(binding.get());
|
|
464
626
|
if (next === null) {
|
|
465
627
|
element.removeAttribute(binding.attr);
|
|
@@ -478,7 +640,7 @@ function mountDescriptor(descriptor, target, slots, context) {
|
|
|
478
640
|
}
|
|
479
641
|
if (!nodes) element.removeAttribute(`data-o-on-${binding.event}`);
|
|
480
642
|
let currentHandler;
|
|
481
|
-
const stop =
|
|
643
|
+
const stop = createDescriptorEffect(context, () => {
|
|
482
644
|
currentHandler = binding.get();
|
|
483
645
|
});
|
|
484
646
|
const listener = (event) => {
|
|
@@ -514,7 +676,7 @@ function mountDescriptor(descriptor, target, slots, context) {
|
|
|
514
676
|
let lastHtml = "__OLOVA_INIT__";
|
|
515
677
|
let cleanupJsxEvents = () => {
|
|
516
678
|
};
|
|
517
|
-
const stop =
|
|
679
|
+
const stop = createDescriptorEffect(context, () => {
|
|
518
680
|
const nextHtml = toHtml(binding.get());
|
|
519
681
|
if (nextHtml === lastHtml) {
|
|
520
682
|
return;
|
|
@@ -550,7 +712,15 @@ function mountDescriptor(descriptor, target, slots, context) {
|
|
|
550
712
|
range.deleteContents();
|
|
551
713
|
continue;
|
|
552
714
|
}
|
|
553
|
-
const slotDescriptor =
|
|
715
|
+
const slotDescriptor = runWithRuntimeErrorHandler(
|
|
716
|
+
context,
|
|
717
|
+
`Failed to render slot "${binding.name}"`,
|
|
718
|
+
slotFactory
|
|
719
|
+
);
|
|
720
|
+
if (!slotDescriptor) {
|
|
721
|
+
range.deleteContents();
|
|
722
|
+
continue;
|
|
723
|
+
}
|
|
554
724
|
const disposeSlot = mountDescriptor(slotDescriptor, range, slots, context);
|
|
555
725
|
cleanups.push(disposeSlot);
|
|
556
726
|
}
|
|
@@ -573,17 +743,17 @@ function mountDescriptor(descriptor, target, slots, context) {
|
|
|
573
743
|
let lastComponent = null;
|
|
574
744
|
let lastProps;
|
|
575
745
|
let lastSlots;
|
|
576
|
-
const stop =
|
|
746
|
+
const stop = createDescriptorEffect(context, () => {
|
|
577
747
|
const nextComponent = binding.getComponent();
|
|
578
748
|
const nextProps = binding.getProps();
|
|
579
749
|
const nextSlots = binding.getSlots ? binding.getSlots() : EMPTY_SLOTS;
|
|
580
|
-
if (lastComponent === nextComponent &&
|
|
750
|
+
if (lastComponent === nextComponent && shallowComparablePropsEqual(lastProps, nextProps) && shallowEqualSlots(lastSlots, nextSlots)) {
|
|
581
751
|
return;
|
|
582
752
|
}
|
|
583
753
|
disposeChild();
|
|
584
754
|
disposeChild = mount(nextComponent, range, nextProps, nextSlots, context);
|
|
585
755
|
lastComponent = nextComponent;
|
|
586
|
-
lastProps =
|
|
756
|
+
lastProps = createComparablePropsSnapshot(nextProps);
|
|
587
757
|
lastSlots = nextSlots;
|
|
588
758
|
});
|
|
589
759
|
cleanups.push(() => {
|
|
@@ -609,17 +779,39 @@ function mountDescriptor(descriptor, target, slots, context) {
|
|
|
609
779
|
let disposeBranch = () => {
|
|
610
780
|
};
|
|
611
781
|
let lastCondition = void 0;
|
|
612
|
-
const stop =
|
|
782
|
+
const stop = createDescriptorEffect(context, () => {
|
|
613
783
|
const condition = !!binding.get();
|
|
614
784
|
if (condition === lastCondition) {
|
|
615
785
|
return;
|
|
616
786
|
}
|
|
617
787
|
disposeBranch();
|
|
618
788
|
if (condition) {
|
|
619
|
-
const branchDescriptor =
|
|
789
|
+
const branchDescriptor = runWithRuntimeErrorHandler(
|
|
790
|
+
context,
|
|
791
|
+
"Failed to render conditional branch",
|
|
792
|
+
binding.trueBranch
|
|
793
|
+
);
|
|
794
|
+
if (!branchDescriptor) {
|
|
795
|
+
range.deleteContents();
|
|
796
|
+
disposeBranch = () => {
|
|
797
|
+
};
|
|
798
|
+
lastCondition = condition;
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
620
801
|
disposeBranch = mountDescriptor(branchDescriptor, range, slots, context);
|
|
621
802
|
} else if (binding.falseBranch) {
|
|
622
|
-
const branchDescriptor =
|
|
803
|
+
const branchDescriptor = runWithRuntimeErrorHandler(
|
|
804
|
+
context,
|
|
805
|
+
"Failed to render conditional fallback branch",
|
|
806
|
+
binding.falseBranch
|
|
807
|
+
);
|
|
808
|
+
if (!branchDescriptor) {
|
|
809
|
+
range.deleteContents();
|
|
810
|
+
disposeBranch = () => {
|
|
811
|
+
};
|
|
812
|
+
lastCondition = condition;
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
623
815
|
disposeBranch = mountDescriptor(branchDescriptor, range, slots, context);
|
|
624
816
|
} else {
|
|
625
817
|
range.deleteContents();
|
|
@@ -655,22 +847,69 @@ function unregisterMountedInstance(instance) {
|
|
|
655
847
|
function renderMountedInstance(instance, restoredValues) {
|
|
656
848
|
const context = new Map(instance.parentContext ?? []);
|
|
657
849
|
const previousContext = currentSetupContext;
|
|
850
|
+
const previousLifecycleHooks = currentLifecycleHooks;
|
|
851
|
+
const lifecycleHooks = createLifecycleHooks();
|
|
658
852
|
currentSetupContext = context;
|
|
853
|
+
currentLifecycleHooks = lifecycleHooks;
|
|
659
854
|
beginHmrStateCapture(restoredValues);
|
|
660
|
-
|
|
661
|
-
const
|
|
662
|
-
instance.disposeDescriptor = mountDescriptor(
|
|
855
|
+
const finalizeRender = (descriptor) => {
|
|
856
|
+
const disposeDescriptor = mountDescriptor(
|
|
663
857
|
descriptor,
|
|
664
858
|
instance.target,
|
|
665
859
|
instance.slots,
|
|
666
860
|
context
|
|
667
861
|
);
|
|
862
|
+
const disposeLifecycle = flushLifecycleHooks(lifecycleHooks, context);
|
|
863
|
+
instance.disposeDescriptor = () => {
|
|
864
|
+
disposeLifecycle();
|
|
865
|
+
disposeDescriptor();
|
|
866
|
+
};
|
|
867
|
+
};
|
|
868
|
+
try {
|
|
869
|
+
const descriptor = runWithRuntimeErrorHandler(
|
|
870
|
+
context,
|
|
871
|
+
"Failed to render component setup",
|
|
872
|
+
() => instance.component.setup(instance.props, instance.slots)
|
|
873
|
+
);
|
|
874
|
+
if (!descriptor) {
|
|
875
|
+
instance.disposeDescriptor = () => {
|
|
876
|
+
};
|
|
877
|
+
instance.hmrSignals = endHmrStateCapture();
|
|
878
|
+
return;
|
|
879
|
+
}
|
|
880
|
+
if (isPromiseLike(descriptor)) {
|
|
881
|
+
const suspenseBoundary = context.get(SUSPENSE_BOUNDARY);
|
|
882
|
+
const settleSuspense = suspenseBoundary?.begin() ?? (() => {
|
|
883
|
+
});
|
|
884
|
+
let disposed = false;
|
|
885
|
+
instance.disposeDescriptor = () => {
|
|
886
|
+
disposed = true;
|
|
887
|
+
settleSuspense();
|
|
888
|
+
};
|
|
889
|
+
instance.hmrSignals = endHmrStateCapture();
|
|
890
|
+
descriptor.then((resolvedDescriptor) => {
|
|
891
|
+
if (disposed) {
|
|
892
|
+
return;
|
|
893
|
+
}
|
|
894
|
+
settleSuspense();
|
|
895
|
+
finalizeRender(resolvedDescriptor);
|
|
896
|
+
}).catch((error) => {
|
|
897
|
+
settleSuspense();
|
|
898
|
+
if (disposed) {
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
handleRuntimeError(error, "Failed to resolve async component", context);
|
|
902
|
+
});
|
|
903
|
+
return;
|
|
904
|
+
}
|
|
905
|
+
finalizeRender(descriptor);
|
|
668
906
|
instance.hmrSignals = endHmrStateCapture();
|
|
669
907
|
} catch (error) {
|
|
670
908
|
endHmrStateCapture();
|
|
671
909
|
throw error;
|
|
672
910
|
} finally {
|
|
673
911
|
currentSetupContext = previousContext;
|
|
912
|
+
currentLifecycleHooks = previousLifecycleHooks;
|
|
674
913
|
}
|
|
675
914
|
}
|
|
676
915
|
function collectHmrSignalValues(instance) {
|
|
@@ -714,6 +953,124 @@ function replaceComponent(current, next) {
|
|
|
714
953
|
function defineComponent(setup, hmrId) {
|
|
715
954
|
return { setup, __hmrId: hmrId };
|
|
716
955
|
}
|
|
956
|
+
function isOlovaComponent(value) {
|
|
957
|
+
return typeof value === "object" && value !== null && "setup" in value;
|
|
958
|
+
}
|
|
959
|
+
function onMount(fn) {
|
|
960
|
+
if (!currentLifecycleHooks) {
|
|
961
|
+
throw new Error("[olova] onMount() can only be used during component setup.");
|
|
962
|
+
}
|
|
963
|
+
currentLifecycleHooks.mount.push(fn);
|
|
964
|
+
}
|
|
965
|
+
function onCleanup(fn) {
|
|
966
|
+
if (!currentLifecycleHooks) {
|
|
967
|
+
throw new Error("[olova] onCleanup() can only be used during component setup.");
|
|
968
|
+
}
|
|
969
|
+
currentLifecycleHooks.cleanup.push(fn);
|
|
970
|
+
}
|
|
971
|
+
function createErrorBoundary(component, fallback) {
|
|
972
|
+
return defineComponent((props, slots) => {
|
|
973
|
+
const errorState = state(null);
|
|
974
|
+
setContext(ERROR_BOUNDARY, (error) => {
|
|
975
|
+
errorState.value = error;
|
|
976
|
+
});
|
|
977
|
+
const renderFallback = () => {
|
|
978
|
+
const error = errorState.value ?? new Error("[olova] Unknown boundary error.");
|
|
979
|
+
if (isOlovaComponent(fallback)) {
|
|
980
|
+
return {
|
|
981
|
+
template: "__O_COMP_boundary_fallback__",
|
|
982
|
+
textBindings: [],
|
|
983
|
+
htmlBindings: [],
|
|
984
|
+
attrBindings: [],
|
|
985
|
+
eventBindings: [],
|
|
986
|
+
slotBindings: [],
|
|
987
|
+
componentBindings: [
|
|
988
|
+
{
|
|
989
|
+
id: "boundary_fallback",
|
|
990
|
+
getComponent: () => fallback,
|
|
991
|
+
getProps: () => ({ error })
|
|
992
|
+
}
|
|
993
|
+
],
|
|
994
|
+
ifBindings: []
|
|
995
|
+
};
|
|
996
|
+
}
|
|
997
|
+
return fallback(error);
|
|
998
|
+
};
|
|
999
|
+
return {
|
|
1000
|
+
template: "__O_IF_boundary__",
|
|
1001
|
+
textBindings: [],
|
|
1002
|
+
htmlBindings: [],
|
|
1003
|
+
attrBindings: [],
|
|
1004
|
+
eventBindings: [],
|
|
1005
|
+
slotBindings: [],
|
|
1006
|
+
componentBindings: [],
|
|
1007
|
+
ifBindings: [
|
|
1008
|
+
{
|
|
1009
|
+
id: "boundary",
|
|
1010
|
+
get: () => errorState.value === null,
|
|
1011
|
+
trueBranch: () => ({
|
|
1012
|
+
template: "__O_COMP_boundary_child__",
|
|
1013
|
+
textBindings: [],
|
|
1014
|
+
htmlBindings: [],
|
|
1015
|
+
attrBindings: [],
|
|
1016
|
+
eventBindings: [],
|
|
1017
|
+
slotBindings: [],
|
|
1018
|
+
componentBindings: [
|
|
1019
|
+
{
|
|
1020
|
+
id: "boundary_child",
|
|
1021
|
+
getComponent: () => component,
|
|
1022
|
+
getProps: () => props,
|
|
1023
|
+
getSlots: () => slots
|
|
1024
|
+
}
|
|
1025
|
+
],
|
|
1026
|
+
ifBindings: []
|
|
1027
|
+
}),
|
|
1028
|
+
falseBranch: renderFallback
|
|
1029
|
+
}
|
|
1030
|
+
]
|
|
1031
|
+
};
|
|
1032
|
+
}, component.__hmrId ? `${component.__hmrId}:boundary` : void 0);
|
|
1033
|
+
}
|
|
1034
|
+
var Suspense = defineComponent((_props, slots) => {
|
|
1035
|
+
const pending = state(0);
|
|
1036
|
+
setContext(SUSPENSE_BOUNDARY, {
|
|
1037
|
+
begin() {
|
|
1038
|
+
pending.value += 1;
|
|
1039
|
+
let settled = false;
|
|
1040
|
+
return () => {
|
|
1041
|
+
if (settled) {
|
|
1042
|
+
return;
|
|
1043
|
+
}
|
|
1044
|
+
settled = true;
|
|
1045
|
+
pending.value = Math.max(0, pending.value - 1);
|
|
1046
|
+
};
|
|
1047
|
+
}
|
|
1048
|
+
});
|
|
1049
|
+
return {
|
|
1050
|
+
template: `<div style="__O_ATTR_default_style__">__O_SLOT_default__</div><div style="__O_ATTR_fallback_style__">__O_SLOT_fallback__</div>`,
|
|
1051
|
+
textBindings: [],
|
|
1052
|
+
htmlBindings: [],
|
|
1053
|
+
attrBindings: [
|
|
1054
|
+
{
|
|
1055
|
+
id: "default_style",
|
|
1056
|
+
attr: "style",
|
|
1057
|
+
get: () => pending.value === 0 ? null : "display:none"
|
|
1058
|
+
},
|
|
1059
|
+
{
|
|
1060
|
+
id: "fallback_style",
|
|
1061
|
+
attr: "style",
|
|
1062
|
+
get: () => pending.value > 0 ? null : "display:none"
|
|
1063
|
+
}
|
|
1064
|
+
],
|
|
1065
|
+
eventBindings: [],
|
|
1066
|
+
slotBindings: [
|
|
1067
|
+
{ id: "default", name: "default" },
|
|
1068
|
+
{ id: "fallback", name: "fallback" }
|
|
1069
|
+
],
|
|
1070
|
+
componentBindings: [],
|
|
1071
|
+
ifBindings: []
|
|
1072
|
+
};
|
|
1073
|
+
});
|
|
717
1074
|
function dangerouslySetHtml(value) {
|
|
718
1075
|
return {
|
|
719
1076
|
__dangerousHtml: true,
|
|
@@ -745,7 +1102,12 @@ function mount(component, target, props = {}, slots = EMPTY_SLOTS, parentContext
|
|
|
745
1102
|
hmrSignals: []
|
|
746
1103
|
};
|
|
747
1104
|
registerMountedInstance(instance);
|
|
748
|
-
|
|
1105
|
+
try {
|
|
1106
|
+
renderMountedInstance(instance);
|
|
1107
|
+
} catch (error) {
|
|
1108
|
+
unregisterMountedInstance(instance);
|
|
1109
|
+
throw toOlovaError(error, "Failed to mount component");
|
|
1110
|
+
}
|
|
749
1111
|
return () => {
|
|
750
1112
|
unregisterMountedInstance(instance);
|
|
751
1113
|
instance.disposeDescriptor();
|
|
@@ -756,7 +1118,7 @@ function createApp(root) {
|
|
|
756
1118
|
mount(target) {
|
|
757
1119
|
const element = typeof target === "string" ? document.querySelector(target) : target;
|
|
758
1120
|
if (!element) {
|
|
759
|
-
throw new Error(`Target not found: ${String(target)}`);
|
|
1121
|
+
throw new Error(`[olova] Target not found: ${String(target)}`);
|
|
760
1122
|
}
|
|
761
1123
|
return mount(root, element);
|
|
762
1124
|
}
|
|
@@ -819,9 +1181,6 @@ function setupPersistence(name, stateRef, target) {
|
|
|
819
1181
|
function ensureState(name, initial, options) {
|
|
820
1182
|
const existing = globalStates.get(name);
|
|
821
1183
|
if (existing) {
|
|
822
|
-
if (existing.value === void 0 && initial !== void 0) {
|
|
823
|
-
existing.value = initial;
|
|
824
|
-
}
|
|
825
1184
|
if (options?.persist) {
|
|
826
1185
|
if (existing.value === void 0) {
|
|
827
1186
|
const persisted = readPersisted(name, options.persist);
|
|
@@ -831,6 +1190,9 @@ function ensureState(name, initial, options) {
|
|
|
831
1190
|
}
|
|
832
1191
|
setupPersistence(name, existing, options.persist);
|
|
833
1192
|
}
|
|
1193
|
+
if (existing.value === void 0 && initial !== void 0) {
|
|
1194
|
+
existing.value = initial;
|
|
1195
|
+
}
|
|
834
1196
|
return existing;
|
|
835
1197
|
}
|
|
836
1198
|
let resolvedInitial = initial;
|
|
@@ -859,6 +1221,6 @@ var global = {
|
|
|
859
1221
|
}
|
|
860
1222
|
};
|
|
861
1223
|
|
|
862
|
-
export { Signal, beginHmrStateCapture, computed, createApp, dangerouslySetHtml, defineComponent, derived, effect, endHmrStateCapture, getContext, global, hasContext, mount, replaceComponent, setContext, state };
|
|
1224
|
+
export { Signal, Suspense, beginHmrStateCapture, computed, createApp, createErrorBoundary, dangerouslySetHtml, defineComponent, derived, effect, endHmrStateCapture, getContext, getReactiveProxyVersion, global, hasContext, mount, onCleanup, onMount, replaceComponent, setContext, state, withRuntimeErrorHandler };
|
|
863
1225
|
//# sourceMappingURL=core.js.map
|
|
864
1226
|
//# sourceMappingURL=core.js.map
|