@cajoa/core 0.10.1 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +144 -12
- package/dist/index.d.cts +14 -6
- package/dist/index.d.ts +14 -6
- package/dist/index.js +142 -12
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -20,10 +20,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
ErrorBoundary: () => ErrorBoundary,
|
|
23
24
|
For: () => For,
|
|
24
25
|
Fragment: () => Fragment,
|
|
25
26
|
Show: () => Show,
|
|
26
27
|
batch: () => batch,
|
|
28
|
+
catchError: () => catchError,
|
|
27
29
|
createContext: () => createContext,
|
|
28
30
|
createEffect: () => createEffect,
|
|
29
31
|
createMemo: () => createMemo,
|
|
@@ -44,6 +46,19 @@ __export(index_exports, {
|
|
|
44
46
|
});
|
|
45
47
|
module.exports = __toCommonJS(index_exports);
|
|
46
48
|
|
|
49
|
+
// src/dev.ts
|
|
50
|
+
function isDev() {
|
|
51
|
+
return globalThis.__CAJOA_DEV__ === true;
|
|
52
|
+
}
|
|
53
|
+
function warn(message) {
|
|
54
|
+
if (isDev() && typeof console !== "undefined")
|
|
55
|
+
console.warn(`[cajoa] ${message}`);
|
|
56
|
+
}
|
|
57
|
+
function logError(message, error) {
|
|
58
|
+
if (isDev() && typeof console !== "undefined")
|
|
59
|
+
console.error(`[cajoa] ${message}`, error);
|
|
60
|
+
}
|
|
61
|
+
|
|
47
62
|
// src/reactivity/signal.ts
|
|
48
63
|
var currentOwner = null;
|
|
49
64
|
var currentEffect = null;
|
|
@@ -57,6 +72,18 @@ function cleanComputation(c) {
|
|
|
57
72
|
c.deps.clear();
|
|
58
73
|
clean(c);
|
|
59
74
|
}
|
|
75
|
+
function addCleanup(fn) {
|
|
76
|
+
currentOwner?.cleanups.push(fn);
|
|
77
|
+
}
|
|
78
|
+
function handleError(error, owner) {
|
|
79
|
+
for (let o = owner; o; o = o.parent) {
|
|
80
|
+
if (o.errorHandler) {
|
|
81
|
+
o.errorHandler(error);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
60
87
|
var batchDepth = 0;
|
|
61
88
|
var pending = /* @__PURE__ */ new Set();
|
|
62
89
|
function flush() {
|
|
@@ -109,20 +136,27 @@ function createEffect(fn) {
|
|
|
109
136
|
currentEffect = effect;
|
|
110
137
|
try {
|
|
111
138
|
fn();
|
|
139
|
+
} catch (error) {
|
|
140
|
+
handleError(error, effect);
|
|
112
141
|
} finally {
|
|
113
142
|
currentOwner = prevOwner;
|
|
114
143
|
currentEffect = prevEffect;
|
|
115
144
|
}
|
|
116
145
|
}
|
|
117
146
|
};
|
|
118
|
-
|
|
147
|
+
addCleanup(() => {
|
|
119
148
|
effect.disposed = true;
|
|
120
149
|
cleanComputation(effect);
|
|
121
150
|
});
|
|
122
151
|
effect.run();
|
|
123
152
|
}
|
|
124
153
|
function onCleanup(fn) {
|
|
125
|
-
currentOwner
|
|
154
|
+
if (!currentOwner) {
|
|
155
|
+
warn(
|
|
156
|
+
"onCleanup() was called outside of a component or effect, so this cleanup will never run."
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
addCleanup(fn);
|
|
126
160
|
}
|
|
127
161
|
function createRoot(fn) {
|
|
128
162
|
const root = { cleanups: [], parent: currentOwner };
|
|
@@ -146,12 +180,48 @@ function onMount(fn) {
|
|
|
146
180
|
currentEffect = null;
|
|
147
181
|
try {
|
|
148
182
|
fn();
|
|
183
|
+
} catch (error) {
|
|
184
|
+
handleError(error, owner);
|
|
149
185
|
} finally {
|
|
150
186
|
currentOwner = prevOwner;
|
|
151
187
|
currentEffect = prevEffect;
|
|
152
188
|
}
|
|
153
189
|
});
|
|
154
190
|
}
|
|
191
|
+
function untrack(fn) {
|
|
192
|
+
const prev = currentEffect;
|
|
193
|
+
currentEffect = null;
|
|
194
|
+
try {
|
|
195
|
+
return fn();
|
|
196
|
+
} finally {
|
|
197
|
+
currentEffect = prev;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
function catchError(fn, handler) {
|
|
201
|
+
const owner = {
|
|
202
|
+
cleanups: [],
|
|
203
|
+
parent: currentOwner,
|
|
204
|
+
errorHandler: handler
|
|
205
|
+
};
|
|
206
|
+
addCleanup(() => clean(owner));
|
|
207
|
+
const prevOwner = currentOwner;
|
|
208
|
+
currentOwner = owner;
|
|
209
|
+
let result;
|
|
210
|
+
let thrown = null;
|
|
211
|
+
try {
|
|
212
|
+
result = fn();
|
|
213
|
+
} catch (error) {
|
|
214
|
+
clean(owner);
|
|
215
|
+
thrown = { error };
|
|
216
|
+
} finally {
|
|
217
|
+
currentOwner = prevOwner;
|
|
218
|
+
}
|
|
219
|
+
if (thrown) {
|
|
220
|
+
handler(thrown.error);
|
|
221
|
+
return void 0;
|
|
222
|
+
}
|
|
223
|
+
return result;
|
|
224
|
+
}
|
|
155
225
|
function createContext(defaultValue) {
|
|
156
226
|
return { id: /* @__PURE__ */ Symbol("cajoa-context"), defaultValue };
|
|
157
227
|
}
|
|
@@ -161,7 +231,7 @@ function provide(ctx, value, fn) {
|
|
|
161
231
|
parent: currentOwner,
|
|
162
232
|
context: /* @__PURE__ */ new Map([[ctx.id, value]])
|
|
163
233
|
};
|
|
164
|
-
|
|
234
|
+
addCleanup(() => clean(owner));
|
|
165
235
|
const prev = currentOwner;
|
|
166
236
|
currentOwner = owner;
|
|
167
237
|
try {
|
|
@@ -171,20 +241,16 @@ function provide(ctx, value, fn) {
|
|
|
171
241
|
}
|
|
172
242
|
}
|
|
173
243
|
function useContext(ctx) {
|
|
244
|
+
if (!currentOwner) {
|
|
245
|
+
warn(
|
|
246
|
+
"useContext() was called outside of a component or effect, so it can only return the default value. Call it at the top of your component and use the value later."
|
|
247
|
+
);
|
|
248
|
+
}
|
|
174
249
|
for (let o = currentOwner; o; o = o.parent) {
|
|
175
250
|
if (o.context?.has(ctx.id)) return o.context.get(ctx.id);
|
|
176
251
|
}
|
|
177
252
|
return ctx.defaultValue;
|
|
178
253
|
}
|
|
179
|
-
function untrack(fn) {
|
|
180
|
-
const prev = currentEffect;
|
|
181
|
-
currentEffect = null;
|
|
182
|
-
try {
|
|
183
|
-
return fn();
|
|
184
|
-
} finally {
|
|
185
|
-
currentEffect = prev;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
254
|
|
|
189
255
|
// src/reactivity/memo.ts
|
|
190
256
|
function createMemo(fn) {
|
|
@@ -273,6 +339,11 @@ function render(component, container) {
|
|
|
273
339
|
return createRoot((dispose) => {
|
|
274
340
|
const r = getRenderer();
|
|
275
341
|
const node = component();
|
|
342
|
+
if (typeof node === "function") {
|
|
343
|
+
throw new Error(
|
|
344
|
+
"render(): the component returned a function (for example <Show>, <For>, <Router> or <ErrorBoundary>). Wrap it in an element, such as <div>\u2026</div>."
|
|
345
|
+
);
|
|
346
|
+
}
|
|
276
347
|
r.clear(container);
|
|
277
348
|
r.insert(container, node);
|
|
278
349
|
return () => {
|
|
@@ -304,6 +375,11 @@ function For(props) {
|
|
|
304
375
|
const nodes = [];
|
|
305
376
|
items.forEach((item, i) => {
|
|
306
377
|
const k = props.key ? props.key(item, i) : item;
|
|
378
|
+
if (next.has(k)) {
|
|
379
|
+
warn(
|
|
380
|
+
`<For> found a duplicate key (${String(k)}). Keys must be unique, otherwise one item replaces another.`
|
|
381
|
+
);
|
|
382
|
+
}
|
|
307
383
|
let entry = cache.get(k);
|
|
308
384
|
if (!entry) {
|
|
309
385
|
entry = createRoot((dispose) => ({
|
|
@@ -322,6 +398,60 @@ function For(props) {
|
|
|
322
398
|
};
|
|
323
399
|
}
|
|
324
400
|
|
|
401
|
+
// src/components/error-boundary.ts
|
|
402
|
+
function resolve2(value) {
|
|
403
|
+
let current2 = value;
|
|
404
|
+
while (typeof current2 === "function") {
|
|
405
|
+
current2 = current2();
|
|
406
|
+
}
|
|
407
|
+
return current2;
|
|
408
|
+
}
|
|
409
|
+
function ErrorBoundary(props) {
|
|
410
|
+
const [version, setVersion] = createSignal(0);
|
|
411
|
+
let failure = null;
|
|
412
|
+
const caught = (error) => {
|
|
413
|
+
logError("ErrorBoundary caught an error:", error);
|
|
414
|
+
props.onError?.(error);
|
|
415
|
+
};
|
|
416
|
+
const reset = () => {
|
|
417
|
+
failure = null;
|
|
418
|
+
setVersion((v) => v + 1);
|
|
419
|
+
};
|
|
420
|
+
const fail = (error) => {
|
|
421
|
+
caught(error);
|
|
422
|
+
failure = { error };
|
|
423
|
+
setVersion((v) => v + 1);
|
|
424
|
+
};
|
|
425
|
+
const showFallback = (error) => typeof props.fallback === "function" ? props.fallback(
|
|
426
|
+
error,
|
|
427
|
+
reset
|
|
428
|
+
) : props.fallback;
|
|
429
|
+
return () => {
|
|
430
|
+
version();
|
|
431
|
+
const current2 = failure;
|
|
432
|
+
if (current2) return untrack(() => showFallback(current2.error));
|
|
433
|
+
let creating = true;
|
|
434
|
+
let early = null;
|
|
435
|
+
const content = untrack(
|
|
436
|
+
() => catchError(
|
|
437
|
+
() => resolve2(props.children ?? null),
|
|
438
|
+
(error) => {
|
|
439
|
+
if (creating) early = { error };
|
|
440
|
+
else fail(error);
|
|
441
|
+
}
|
|
442
|
+
)
|
|
443
|
+
);
|
|
444
|
+
creating = false;
|
|
445
|
+
const first = early;
|
|
446
|
+
if (first) {
|
|
447
|
+
caught(first.error);
|
|
448
|
+
failure = first;
|
|
449
|
+
return untrack(() => showFallback(first.error));
|
|
450
|
+
}
|
|
451
|
+
return content;
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
|
|
325
455
|
// src/jsx-runtime.ts
|
|
326
456
|
function jsx(type, props) {
|
|
327
457
|
if (typeof type === "function") return type(props ?? {});
|
|
@@ -338,10 +468,12 @@ function Fragment(props) {
|
|
|
338
468
|
}
|
|
339
469
|
// Annotate the CommonJS export names for ESM import in node:
|
|
340
470
|
0 && (module.exports = {
|
|
471
|
+
ErrorBoundary,
|
|
341
472
|
For,
|
|
342
473
|
Fragment,
|
|
343
474
|
Show,
|
|
344
475
|
batch,
|
|
476
|
+
catchError,
|
|
345
477
|
createContext,
|
|
346
478
|
createEffect,
|
|
347
479
|
createMemo,
|
package/dist/index.d.cts
CHANGED
|
@@ -5,6 +5,8 @@ declare function createEffect(fn: () => void): void;
|
|
|
5
5
|
declare function onCleanup(fn: Cleanup): void;
|
|
6
6
|
declare function createRoot<T>(fn: (dispose: () => void) => T): T;
|
|
7
7
|
declare function onMount(fn: () => void): void;
|
|
8
|
+
declare function untrack<T>(fn: () => T): T;
|
|
9
|
+
declare function catchError<T>(fn: () => T, handler: (error: unknown) => void): T | undefined;
|
|
8
10
|
interface Context<T> {
|
|
9
11
|
readonly id: symbol;
|
|
10
12
|
readonly defaultValue: T;
|
|
@@ -12,7 +14,6 @@ interface Context<T> {
|
|
|
12
14
|
declare function createContext<T>(defaultValue: T): Context<T>;
|
|
13
15
|
declare function provide<T, R>(ctx: Context<T>, value: T, fn: () => R): R;
|
|
14
16
|
declare function useContext<T>(ctx: Context<T>): T;
|
|
15
|
-
declare function untrack<T>(fn: () => T): T;
|
|
16
17
|
|
|
17
18
|
declare function createMemo<T>(fn: () => T): () => T;
|
|
18
19
|
|
|
@@ -36,11 +37,11 @@ declare function h(tag: string, props: Record<string, any> | null, ...children:
|
|
|
36
37
|
|
|
37
38
|
declare function render(component: () => HostNode, container: HostNode): () => void;
|
|
38
39
|
|
|
39
|
-
type Lazy<T> = T | (() => T);
|
|
40
|
+
type Lazy$1<T> = T | (() => T);
|
|
40
41
|
declare function Show<T>(props: {
|
|
41
|
-
when: Lazy<T>;
|
|
42
|
-
children?: Lazy<Child>;
|
|
43
|
-
fallback?: Lazy<Child>;
|
|
42
|
+
when: Lazy$1<T>;
|
|
43
|
+
children?: Lazy$1<Child>;
|
|
44
|
+
fallback?: Lazy$1<Child>;
|
|
44
45
|
}): () => string | number | boolean | object | null;
|
|
45
46
|
|
|
46
47
|
declare function For<T>(props: {
|
|
@@ -49,6 +50,13 @@ declare function For<T>(props: {
|
|
|
49
50
|
key?: (item: T, index: number) => unknown;
|
|
50
51
|
}): () => object[];
|
|
51
52
|
|
|
53
|
+
type Lazy<T> = T | (() => T);
|
|
54
|
+
declare function ErrorBoundary(props: {
|
|
55
|
+
fallback: Child | ((error: unknown, reset: () => void) => Child);
|
|
56
|
+
children?: Lazy<Child>;
|
|
57
|
+
onError?: (error: unknown) => void;
|
|
58
|
+
}): () => Child;
|
|
59
|
+
|
|
52
60
|
declare function jsx(type: any, props: Record<string, any> | null): any;
|
|
53
61
|
declare const jsxs: typeof jsx;
|
|
54
62
|
declare const jsxDEV: typeof jsx;
|
|
@@ -68,5 +76,5 @@ declare function Fragment(props: {
|
|
|
68
76
|
declare function setRenderer(renderer: Renderer): void;
|
|
69
77
|
declare function getRenderer(): Renderer;
|
|
70
78
|
|
|
71
|
-
export { For, Fragment, JSX, Show, batch, createContext, createEffect, createMemo, createRoot, createSignal, getRenderer, h, jsx, jsxDEV, jsxs, onCleanup, onMount, provide, render, setRenderer, untrack, useContext };
|
|
79
|
+
export { ErrorBoundary, For, Fragment, JSX, Show, batch, catchError, createContext, createEffect, createMemo, createRoot, createSignal, getRenderer, h, jsx, jsxDEV, jsxs, onCleanup, onMount, provide, render, setRenderer, untrack, useContext };
|
|
72
80
|
export type { Child, Context, HostNode, Renderer };
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ declare function createEffect(fn: () => void): void;
|
|
|
5
5
|
declare function onCleanup(fn: Cleanup): void;
|
|
6
6
|
declare function createRoot<T>(fn: (dispose: () => void) => T): T;
|
|
7
7
|
declare function onMount(fn: () => void): void;
|
|
8
|
+
declare function untrack<T>(fn: () => T): T;
|
|
9
|
+
declare function catchError<T>(fn: () => T, handler: (error: unknown) => void): T | undefined;
|
|
8
10
|
interface Context<T> {
|
|
9
11
|
readonly id: symbol;
|
|
10
12
|
readonly defaultValue: T;
|
|
@@ -12,7 +14,6 @@ interface Context<T> {
|
|
|
12
14
|
declare function createContext<T>(defaultValue: T): Context<T>;
|
|
13
15
|
declare function provide<T, R>(ctx: Context<T>, value: T, fn: () => R): R;
|
|
14
16
|
declare function useContext<T>(ctx: Context<T>): T;
|
|
15
|
-
declare function untrack<T>(fn: () => T): T;
|
|
16
17
|
|
|
17
18
|
declare function createMemo<T>(fn: () => T): () => T;
|
|
18
19
|
|
|
@@ -36,11 +37,11 @@ declare function h(tag: string, props: Record<string, any> | null, ...children:
|
|
|
36
37
|
|
|
37
38
|
declare function render(component: () => HostNode, container: HostNode): () => void;
|
|
38
39
|
|
|
39
|
-
type Lazy<T> = T | (() => T);
|
|
40
|
+
type Lazy$1<T> = T | (() => T);
|
|
40
41
|
declare function Show<T>(props: {
|
|
41
|
-
when: Lazy<T>;
|
|
42
|
-
children?: Lazy<Child>;
|
|
43
|
-
fallback?: Lazy<Child>;
|
|
42
|
+
when: Lazy$1<T>;
|
|
43
|
+
children?: Lazy$1<Child>;
|
|
44
|
+
fallback?: Lazy$1<Child>;
|
|
44
45
|
}): () => string | number | boolean | object | null;
|
|
45
46
|
|
|
46
47
|
declare function For<T>(props: {
|
|
@@ -49,6 +50,13 @@ declare function For<T>(props: {
|
|
|
49
50
|
key?: (item: T, index: number) => unknown;
|
|
50
51
|
}): () => object[];
|
|
51
52
|
|
|
53
|
+
type Lazy<T> = T | (() => T);
|
|
54
|
+
declare function ErrorBoundary(props: {
|
|
55
|
+
fallback: Child | ((error: unknown, reset: () => void) => Child);
|
|
56
|
+
children?: Lazy<Child>;
|
|
57
|
+
onError?: (error: unknown) => void;
|
|
58
|
+
}): () => Child;
|
|
59
|
+
|
|
52
60
|
declare function jsx(type: any, props: Record<string, any> | null): any;
|
|
53
61
|
declare const jsxs: typeof jsx;
|
|
54
62
|
declare const jsxDEV: typeof jsx;
|
|
@@ -68,5 +76,5 @@ declare function Fragment(props: {
|
|
|
68
76
|
declare function setRenderer(renderer: Renderer): void;
|
|
69
77
|
declare function getRenderer(): Renderer;
|
|
70
78
|
|
|
71
|
-
export { For, Fragment, JSX, Show, batch, createContext, createEffect, createMemo, createRoot, createSignal, getRenderer, h, jsx, jsxDEV, jsxs, onCleanup, onMount, provide, render, setRenderer, untrack, useContext };
|
|
79
|
+
export { ErrorBoundary, For, Fragment, JSX, Show, batch, catchError, createContext, createEffect, createMemo, createRoot, createSignal, getRenderer, h, jsx, jsxDEV, jsxs, onCleanup, onMount, provide, render, setRenderer, untrack, useContext };
|
|
72
80
|
export type { Child, Context, HostNode, Renderer };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
// src/dev.ts
|
|
2
|
+
function isDev() {
|
|
3
|
+
return globalThis.__CAJOA_DEV__ === true;
|
|
4
|
+
}
|
|
5
|
+
function warn(message) {
|
|
6
|
+
if (isDev() && typeof console !== "undefined")
|
|
7
|
+
console.warn(`[cajoa] ${message}`);
|
|
8
|
+
}
|
|
9
|
+
function logError(message, error) {
|
|
10
|
+
if (isDev() && typeof console !== "undefined")
|
|
11
|
+
console.error(`[cajoa] ${message}`, error);
|
|
12
|
+
}
|
|
13
|
+
|
|
1
14
|
// src/reactivity/signal.ts
|
|
2
15
|
var currentOwner = null;
|
|
3
16
|
var currentEffect = null;
|
|
@@ -11,6 +24,18 @@ function cleanComputation(c) {
|
|
|
11
24
|
c.deps.clear();
|
|
12
25
|
clean(c);
|
|
13
26
|
}
|
|
27
|
+
function addCleanup(fn) {
|
|
28
|
+
currentOwner?.cleanups.push(fn);
|
|
29
|
+
}
|
|
30
|
+
function handleError(error, owner) {
|
|
31
|
+
for (let o = owner; o; o = o.parent) {
|
|
32
|
+
if (o.errorHandler) {
|
|
33
|
+
o.errorHandler(error);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
14
39
|
var batchDepth = 0;
|
|
15
40
|
var pending = /* @__PURE__ */ new Set();
|
|
16
41
|
function flush() {
|
|
@@ -63,20 +88,27 @@ function createEffect(fn) {
|
|
|
63
88
|
currentEffect = effect;
|
|
64
89
|
try {
|
|
65
90
|
fn();
|
|
91
|
+
} catch (error) {
|
|
92
|
+
handleError(error, effect);
|
|
66
93
|
} finally {
|
|
67
94
|
currentOwner = prevOwner;
|
|
68
95
|
currentEffect = prevEffect;
|
|
69
96
|
}
|
|
70
97
|
}
|
|
71
98
|
};
|
|
72
|
-
|
|
99
|
+
addCleanup(() => {
|
|
73
100
|
effect.disposed = true;
|
|
74
101
|
cleanComputation(effect);
|
|
75
102
|
});
|
|
76
103
|
effect.run();
|
|
77
104
|
}
|
|
78
105
|
function onCleanup(fn) {
|
|
79
|
-
currentOwner
|
|
106
|
+
if (!currentOwner) {
|
|
107
|
+
warn(
|
|
108
|
+
"onCleanup() was called outside of a component or effect, so this cleanup will never run."
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
addCleanup(fn);
|
|
80
112
|
}
|
|
81
113
|
function createRoot(fn) {
|
|
82
114
|
const root = { cleanups: [], parent: currentOwner };
|
|
@@ -100,12 +132,48 @@ function onMount(fn) {
|
|
|
100
132
|
currentEffect = null;
|
|
101
133
|
try {
|
|
102
134
|
fn();
|
|
135
|
+
} catch (error) {
|
|
136
|
+
handleError(error, owner);
|
|
103
137
|
} finally {
|
|
104
138
|
currentOwner = prevOwner;
|
|
105
139
|
currentEffect = prevEffect;
|
|
106
140
|
}
|
|
107
141
|
});
|
|
108
142
|
}
|
|
143
|
+
function untrack(fn) {
|
|
144
|
+
const prev = currentEffect;
|
|
145
|
+
currentEffect = null;
|
|
146
|
+
try {
|
|
147
|
+
return fn();
|
|
148
|
+
} finally {
|
|
149
|
+
currentEffect = prev;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
function catchError(fn, handler) {
|
|
153
|
+
const owner = {
|
|
154
|
+
cleanups: [],
|
|
155
|
+
parent: currentOwner,
|
|
156
|
+
errorHandler: handler
|
|
157
|
+
};
|
|
158
|
+
addCleanup(() => clean(owner));
|
|
159
|
+
const prevOwner = currentOwner;
|
|
160
|
+
currentOwner = owner;
|
|
161
|
+
let result;
|
|
162
|
+
let thrown = null;
|
|
163
|
+
try {
|
|
164
|
+
result = fn();
|
|
165
|
+
} catch (error) {
|
|
166
|
+
clean(owner);
|
|
167
|
+
thrown = { error };
|
|
168
|
+
} finally {
|
|
169
|
+
currentOwner = prevOwner;
|
|
170
|
+
}
|
|
171
|
+
if (thrown) {
|
|
172
|
+
handler(thrown.error);
|
|
173
|
+
return void 0;
|
|
174
|
+
}
|
|
175
|
+
return result;
|
|
176
|
+
}
|
|
109
177
|
function createContext(defaultValue) {
|
|
110
178
|
return { id: /* @__PURE__ */ Symbol("cajoa-context"), defaultValue };
|
|
111
179
|
}
|
|
@@ -115,7 +183,7 @@ function provide(ctx, value, fn) {
|
|
|
115
183
|
parent: currentOwner,
|
|
116
184
|
context: /* @__PURE__ */ new Map([[ctx.id, value]])
|
|
117
185
|
};
|
|
118
|
-
|
|
186
|
+
addCleanup(() => clean(owner));
|
|
119
187
|
const prev = currentOwner;
|
|
120
188
|
currentOwner = owner;
|
|
121
189
|
try {
|
|
@@ -125,20 +193,16 @@ function provide(ctx, value, fn) {
|
|
|
125
193
|
}
|
|
126
194
|
}
|
|
127
195
|
function useContext(ctx) {
|
|
196
|
+
if (!currentOwner) {
|
|
197
|
+
warn(
|
|
198
|
+
"useContext() was called outside of a component or effect, so it can only return the default value. Call it at the top of your component and use the value later."
|
|
199
|
+
);
|
|
200
|
+
}
|
|
128
201
|
for (let o = currentOwner; o; o = o.parent) {
|
|
129
202
|
if (o.context?.has(ctx.id)) return o.context.get(ctx.id);
|
|
130
203
|
}
|
|
131
204
|
return ctx.defaultValue;
|
|
132
205
|
}
|
|
133
|
-
function untrack(fn) {
|
|
134
|
-
const prev = currentEffect;
|
|
135
|
-
currentEffect = null;
|
|
136
|
-
try {
|
|
137
|
-
return fn();
|
|
138
|
-
} finally {
|
|
139
|
-
currentEffect = prev;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
206
|
|
|
143
207
|
// src/reactivity/memo.ts
|
|
144
208
|
function createMemo(fn) {
|
|
@@ -227,6 +291,11 @@ function render(component, container) {
|
|
|
227
291
|
return createRoot((dispose) => {
|
|
228
292
|
const r = getRenderer();
|
|
229
293
|
const node = component();
|
|
294
|
+
if (typeof node === "function") {
|
|
295
|
+
throw new Error(
|
|
296
|
+
"render(): the component returned a function (for example <Show>, <For>, <Router> or <ErrorBoundary>). Wrap it in an element, such as <div>\u2026</div>."
|
|
297
|
+
);
|
|
298
|
+
}
|
|
230
299
|
r.clear(container);
|
|
231
300
|
r.insert(container, node);
|
|
232
301
|
return () => {
|
|
@@ -258,6 +327,11 @@ function For(props) {
|
|
|
258
327
|
const nodes = [];
|
|
259
328
|
items.forEach((item, i) => {
|
|
260
329
|
const k = props.key ? props.key(item, i) : item;
|
|
330
|
+
if (next.has(k)) {
|
|
331
|
+
warn(
|
|
332
|
+
`<For> found a duplicate key (${String(k)}). Keys must be unique, otherwise one item replaces another.`
|
|
333
|
+
);
|
|
334
|
+
}
|
|
261
335
|
let entry = cache.get(k);
|
|
262
336
|
if (!entry) {
|
|
263
337
|
entry = createRoot((dispose) => ({
|
|
@@ -276,6 +350,60 @@ function For(props) {
|
|
|
276
350
|
};
|
|
277
351
|
}
|
|
278
352
|
|
|
353
|
+
// src/components/error-boundary.ts
|
|
354
|
+
function resolve2(value) {
|
|
355
|
+
let current2 = value;
|
|
356
|
+
while (typeof current2 === "function") {
|
|
357
|
+
current2 = current2();
|
|
358
|
+
}
|
|
359
|
+
return current2;
|
|
360
|
+
}
|
|
361
|
+
function ErrorBoundary(props) {
|
|
362
|
+
const [version, setVersion] = createSignal(0);
|
|
363
|
+
let failure = null;
|
|
364
|
+
const caught = (error) => {
|
|
365
|
+
logError("ErrorBoundary caught an error:", error);
|
|
366
|
+
props.onError?.(error);
|
|
367
|
+
};
|
|
368
|
+
const reset = () => {
|
|
369
|
+
failure = null;
|
|
370
|
+
setVersion((v) => v + 1);
|
|
371
|
+
};
|
|
372
|
+
const fail = (error) => {
|
|
373
|
+
caught(error);
|
|
374
|
+
failure = { error };
|
|
375
|
+
setVersion((v) => v + 1);
|
|
376
|
+
};
|
|
377
|
+
const showFallback = (error) => typeof props.fallback === "function" ? props.fallback(
|
|
378
|
+
error,
|
|
379
|
+
reset
|
|
380
|
+
) : props.fallback;
|
|
381
|
+
return () => {
|
|
382
|
+
version();
|
|
383
|
+
const current2 = failure;
|
|
384
|
+
if (current2) return untrack(() => showFallback(current2.error));
|
|
385
|
+
let creating = true;
|
|
386
|
+
let early = null;
|
|
387
|
+
const content = untrack(
|
|
388
|
+
() => catchError(
|
|
389
|
+
() => resolve2(props.children ?? null),
|
|
390
|
+
(error) => {
|
|
391
|
+
if (creating) early = { error };
|
|
392
|
+
else fail(error);
|
|
393
|
+
}
|
|
394
|
+
)
|
|
395
|
+
);
|
|
396
|
+
creating = false;
|
|
397
|
+
const first = early;
|
|
398
|
+
if (first) {
|
|
399
|
+
caught(first.error);
|
|
400
|
+
failure = first;
|
|
401
|
+
return untrack(() => showFallback(first.error));
|
|
402
|
+
}
|
|
403
|
+
return content;
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
|
|
279
407
|
// src/jsx-runtime.ts
|
|
280
408
|
function jsx(type, props) {
|
|
281
409
|
if (typeof type === "function") return type(props ?? {});
|
|
@@ -291,10 +419,12 @@ function Fragment(props) {
|
|
|
291
419
|
return frag;
|
|
292
420
|
}
|
|
293
421
|
export {
|
|
422
|
+
ErrorBoundary,
|
|
294
423
|
For,
|
|
295
424
|
Fragment,
|
|
296
425
|
Show,
|
|
297
426
|
batch,
|
|
427
|
+
catchError,
|
|
298
428
|
createContext,
|
|
299
429
|
createEffect,
|
|
300
430
|
createMemo,
|