effectweb 0.3.1 → 0.4.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/README.md +35 -4
- package/dist/AsyncContent.d.ts +1 -1
- package/dist/AsyncContent.js +18 -35
- package/dist/cache.d.ts +2 -2
- package/dist/cache.js +7 -3
- package/dist/collection.d.ts +1 -1
- package/dist/collection.js +1 -3
- package/dist/component.js +5 -2
- package/dist/dom.d.ts +26 -23
- package/dist/dom.js +150 -119
- package/dist/effectEvent.d.ts +3 -3
- package/dist/effectEvent.js +27 -39
- package/dist/form.d.ts +2 -1
- package/dist/http.d.ts +2 -1
- package/dist/http.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/infinite-query.d.ts +1 -1
- package/dist/infinite-query.js +1 -1
- package/dist/jsx-runtime.d.ts +6 -0
- package/dist/jsx-runtime.js +14 -1
- package/dist/jsx.d.ts +2 -1
- package/dist/keyed-tasks.d.ts +5 -4
- package/dist/keyed-tasks.js +27 -22
- package/dist/lazy.d.ts +2 -1
- package/dist/lazy.js +13 -8
- package/dist/load.d.ts +1 -1
- package/dist/load.js +1 -1
- package/dist/mount.d.ts +12 -3
- package/dist/mount.js +63 -20
- package/dist/owner.d.ts +8 -6
- package/dist/owner.js +22 -40
- package/dist/pages.d.ts +1 -1
- package/dist/pages.js +2 -1
- package/dist/program.d.ts +7 -5
- package/dist/program.js +33 -20
- package/dist/query-internals.d.ts +1 -1
- package/dist/query.d.ts +1 -1
- package/dist/query.js +0 -2
- package/dist/resource.js +3 -1
- package/dist/runtime.d.ts +2 -1
- package/dist/runtime.js +3 -1
- package/dist/session.js +10 -3
- package/dist/settlement.d.ts +2 -1
- package/dist/settlement.js +13 -8
- package/dist/snapshot.d.ts +1 -1
- package/dist/snapshot.js +10 -12
- package/dist/task.d.ts +1 -1
- package/dist/task.js +3 -1
- package/dist/tasks.d.ts +1 -1
- package/dist/tasks.js +2 -1
- package/dist/testing.d.ts +5 -4
- package/dist/testing.js +4 -2
- package/package.json +1 -1
- package/dist/intrinsic.d.ts +0 -2
- package/dist/intrinsic.js +0 -120
- package/dist/slotIdentity.d.ts +0 -1
- package/dist/slotIdentity.js +0 -2
package/dist/program.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { protectSnapshot } from './snapshot.js';
|
|
2
2
|
import { reportError, reportSafely } from './errors.js';
|
|
3
3
|
import { traceProgram, nextProgramId, hasProgramObservers } from './diagnostics.js';
|
|
4
|
-
import
|
|
4
|
+
import * as Cause from 'effect/Cause';
|
|
5
|
+
import * as Effect from 'effect/Effect';
|
|
6
|
+
import * as Fiber from 'effect/Fiber';
|
|
7
|
+
import * as Option from 'effect/Option';
|
|
8
|
+
import * as Stream from 'effect/Stream';
|
|
5
9
|
export const commandSlot = (name) => Symbol(name);
|
|
6
|
-
const taskPolicies = ['replace', 'drop', 'parallel', 'queue', 'latest-queued'];
|
|
7
10
|
/** A lazy request settles successes, typed failures and defects through one message contract. */
|
|
8
11
|
export function effectCommand(slot, load, handlers) {
|
|
9
12
|
return {
|
|
@@ -68,13 +71,20 @@ export function program(options) {
|
|
|
68
71
|
const notifyStopped = () => {
|
|
69
72
|
if (live.size || running.size || draining)
|
|
70
73
|
return;
|
|
71
|
-
|
|
72
|
-
done();
|
|
74
|
+
const completed = [...stopped];
|
|
73
75
|
stopped.clear();
|
|
76
|
+
for (const done of completed)
|
|
77
|
+
done();
|
|
74
78
|
};
|
|
75
|
-
const awaitStopped = () =>
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
const awaitStopped = () => Effect.callback((resume) => {
|
|
80
|
+
if (live.size === 0 && running.size === 0 && !draining)
|
|
81
|
+
return resume(Effect.void);
|
|
82
|
+
const done = () => resume(Effect.void);
|
|
83
|
+
stopped.add(done);
|
|
84
|
+
return Effect.sync(() => {
|
|
85
|
+
stopped.delete(done);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
78
88
|
let disposed = false;
|
|
79
89
|
let draining = false;
|
|
80
90
|
const queue = [];
|
|
@@ -146,9 +156,12 @@ export function program(options) {
|
|
|
146
156
|
task.fiber = fiber;
|
|
147
157
|
fiber.addObserver((exit) => {
|
|
148
158
|
live.delete(task);
|
|
149
|
-
|
|
150
|
-
|
|
159
|
+
if (!valid()) {
|
|
160
|
+
if (exit._tag === 'Failure' && !Cause.hasInterruptsOnly(exit.cause))
|
|
161
|
+
reportSafely(options.onDefect ?? reportError, exit.cause);
|
|
162
|
+
notifyStopped();
|
|
151
163
|
return;
|
|
164
|
+
}
|
|
152
165
|
group.active.delete(task);
|
|
153
166
|
if (!group.active.size && !group.pending.length)
|
|
154
167
|
running.delete(command.slot);
|
|
@@ -198,10 +211,6 @@ export function program(options) {
|
|
|
198
211
|
}
|
|
199
212
|
const { message } = queue.shift();
|
|
200
213
|
const transition = options.update(current, message);
|
|
201
|
-
for (const command of transition.commands ?? []) {
|
|
202
|
-
if (typeof command.slot !== 'symbol' || !taskPolicies.includes(command.policy))
|
|
203
|
-
throw new TypeError('Commands require a commandSlot() token and an explicit concurrency policy.');
|
|
204
|
-
}
|
|
205
214
|
trace('update', undefined, message);
|
|
206
215
|
for (const slot of transition.cancel ?? [])
|
|
207
216
|
cancel(slot);
|
|
@@ -276,17 +285,21 @@ export function program(options) {
|
|
|
276
285
|
};
|
|
277
286
|
return {
|
|
278
287
|
awaitStopped,
|
|
279
|
-
close: () => {
|
|
288
|
+
close: () => Effect.suspend(() => {
|
|
280
289
|
dispose();
|
|
281
290
|
return awaitStopped();
|
|
282
|
-
},
|
|
291
|
+
}),
|
|
283
292
|
model: () => current,
|
|
284
293
|
activeSlots: () => [...running.keys()],
|
|
285
|
-
awaitIdle: (slot) =>
|
|
286
|
-
?
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
294
|
+
awaitIdle: (slot) => Effect.callback((resume) => {
|
|
295
|
+
if (disposed || (!draining && (slot ? !running.has(slot) : running.size === 0)))
|
|
296
|
+
return resume(Effect.void);
|
|
297
|
+
const waiter = { slot, done: () => resume(Effect.void) };
|
|
298
|
+
waiters.add(waiter);
|
|
299
|
+
return Effect.sync(() => {
|
|
300
|
+
waiters.delete(waiter);
|
|
301
|
+
});
|
|
302
|
+
}),
|
|
290
303
|
send,
|
|
291
304
|
subscribe(listener) {
|
|
292
305
|
if (disposed)
|
package/dist/query.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import type * as Effect from 'effect/Effect';
|
|
2
2
|
import { type QueryDefinition } from './query-internals.js';
|
|
3
3
|
/** Canonical data identity: plain objects, dense arrays, and finite scalar values. */
|
|
4
4
|
export type QueryKey = string | number | boolean | null | undefined | readonly QueryKey[] | {
|
package/dist/query.js
CHANGED
|
@@ -54,8 +54,6 @@ export function encodeQueryKey(key) {
|
|
|
54
54
|
return encode(key);
|
|
55
55
|
}
|
|
56
56
|
export function query(definition) {
|
|
57
|
-
if ('key' in definition)
|
|
58
|
-
throw new TypeError('Query identity includes all arguments. Remove key and provide services through the Effect environment.');
|
|
59
57
|
const staleTime = definition.staleTime ?? Infinity;
|
|
60
58
|
if (Number.isNaN(staleTime) || staleTime < 0)
|
|
61
59
|
throw new RangeError('Query staleTime must be nonnegative.');
|
package/dist/resource.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { commandSlot } from './program.js';
|
|
2
|
-
import
|
|
2
|
+
import * as Cause from 'effect/Cause';
|
|
3
|
+
import * as Effect from 'effect/Effect';
|
|
4
|
+
import * as Option from 'effect/Option';
|
|
3
5
|
import * as AsyncResult from 'effect/unstable/reactivity/AsyncResult';
|
|
4
6
|
import { loadEffect } from './load.js';
|
|
5
7
|
import { component } from './component.js';
|
package/dist/runtime.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Snapshot } from './snapshot.js';
|
|
2
|
-
import
|
|
2
|
+
import * as Context from 'effect/Context';
|
|
3
|
+
import * as Effect from 'effect/Effect';
|
|
3
4
|
import { type Command, type RunningProgram, type Transition } from './program.js';
|
|
4
5
|
/** A binding to application-owned services, not a new scope or service lifetime. */
|
|
5
6
|
export interface UiRuntime<R> {
|
package/dist/runtime.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Context from 'effect/Context';
|
|
2
|
+
import * as Effect from 'effect/Effect';
|
|
3
|
+
import * as Stream from 'effect/Stream';
|
|
2
4
|
import { program } from './program.js';
|
|
3
5
|
export function uiRuntime(context) {
|
|
4
6
|
const provide = (effect) => Effect.provideContext(effect, context);
|
package/dist/session.js
CHANGED
|
@@ -192,10 +192,17 @@ export function projectionCache() {
|
|
|
192
192
|
}
|
|
193
193
|
export function sessionGroup(sessions, changed) {
|
|
194
194
|
const scope = lifetime();
|
|
195
|
-
for (const session of sessions)
|
|
195
|
+
for (const session of sessions)
|
|
196
196
|
scope.add(() => session.dispose());
|
|
197
|
-
|
|
198
|
-
|
|
197
|
+
try {
|
|
198
|
+
for (const session of sessions) {
|
|
199
|
+
if (session.subscribe)
|
|
200
|
+
scope.add(session.subscribe(changed));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
scope.dispose();
|
|
205
|
+
throw error;
|
|
199
206
|
}
|
|
200
207
|
return {
|
|
201
208
|
refresh: () => {
|
package/dist/settlement.d.ts
CHANGED
package/dist/settlement.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Internal completion accounting, including reentrant acquisition before a fiber is available. */
|
|
2
2
|
export class Settlement {
|
|
3
3
|
pending = 0;
|
|
4
|
-
waiters =
|
|
4
|
+
waiters = new Set();
|
|
5
5
|
begin() {
|
|
6
6
|
this.pending++;
|
|
7
7
|
let finished = false;
|
|
@@ -11,17 +11,22 @@ export class Settlement {
|
|
|
11
11
|
finished = true;
|
|
12
12
|
if (--this.pending)
|
|
13
13
|
return;
|
|
14
|
-
|
|
14
|
+
const waiters = [...this.waiters];
|
|
15
|
+
this.waiters.clear();
|
|
16
|
+
for (const done of waiters)
|
|
15
17
|
done();
|
|
16
|
-
this.waiters.length = 0;
|
|
17
18
|
};
|
|
18
19
|
}
|
|
19
20
|
wait() {
|
|
20
|
-
return
|
|
21
|
-
if (this.pending)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
return Effect.callback((resume) => {
|
|
22
|
+
if (!this.pending)
|
|
23
|
+
return resume(Effect.void);
|
|
24
|
+
const done = () => resume(Effect.void);
|
|
25
|
+
this.waiters.add(done);
|
|
26
|
+
return Effect.sync(() => {
|
|
27
|
+
this.waiters.delete(done);
|
|
28
|
+
});
|
|
25
29
|
});
|
|
26
30
|
}
|
|
27
31
|
}
|
|
32
|
+
import * as Effect from 'effect/Effect';
|
package/dist/snapshot.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import type * as Effect from 'effect/Effect';
|
|
2
2
|
import type * as AsyncResult from 'effect/unstable/reactivity/AsyncResult';
|
|
3
3
|
/** Mark an application service as opaque to snapshot typing; this is a type-only brand. */
|
|
4
4
|
export declare const snapshotOpaque: unique symbol;
|
package/dist/snapshot.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { isAsyncResult } from 'effect/unstable/reactivity/AsyncResult';
|
|
2
|
-
const
|
|
2
|
+
const protectedValues = new WeakSet();
|
|
3
3
|
/** Protect published plain data in every build. Opaque objects keep their own lifecycle. */
|
|
4
4
|
export function protectSnapshot(value) {
|
|
5
5
|
const seen = new Set();
|
|
6
6
|
const plain = [];
|
|
7
|
-
const
|
|
8
|
-
if (!item || typeof item !== 'object' ||
|
|
7
|
+
const visit = (item) => {
|
|
8
|
+
if (!item || typeof item !== 'object' || protectedValues.has(item) || seen.has(item))
|
|
9
9
|
return;
|
|
10
10
|
seen.add(item);
|
|
11
11
|
// Effect wrappers remain opaque, but their successful UI data is plain data.
|
|
12
12
|
if (isAsyncResult(item)) {
|
|
13
13
|
if (item._tag === 'Success')
|
|
14
|
-
|
|
14
|
+
visit(item.value);
|
|
15
15
|
else if (item._tag === 'Failure' && item.previousSuccess._tag === 'Some')
|
|
16
|
-
|
|
16
|
+
visit(item.previousSuccess.value);
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
19
|
const prototype = Object.getPrototypeOf(item);
|
|
@@ -21,18 +21,16 @@ export function protectSnapshot(value) {
|
|
|
21
21
|
return;
|
|
22
22
|
for (const key of Reflect.ownKeys(item)) {
|
|
23
23
|
const descriptor = Object.getOwnPropertyDescriptor(item, key);
|
|
24
|
-
if (
|
|
25
|
-
|
|
26
|
-
validate(descriptor.value);
|
|
24
|
+
if (Object.hasOwn(descriptor, 'value'))
|
|
25
|
+
visit(descriptor.value);
|
|
27
26
|
}
|
|
28
27
|
plain.push(item);
|
|
29
28
|
};
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
validate(value);
|
|
29
|
+
// Traverse stored data without invoking application getters.
|
|
30
|
+
visit(value);
|
|
33
31
|
for (const item of plain)
|
|
34
32
|
Object.freeze(item);
|
|
35
33
|
for (const item of seen)
|
|
36
|
-
|
|
34
|
+
protectedValues.add(item);
|
|
37
35
|
return value;
|
|
38
36
|
}
|
package/dist/task.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Snapshot } from './snapshot.js';
|
|
2
|
-
import
|
|
2
|
+
import * as Effect from 'effect/Effect';
|
|
3
3
|
import * as AsyncResult from 'effect/unstable/reactivity/AsyncResult';
|
|
4
4
|
import type { View } from './dom.js';
|
|
5
5
|
import { type Send, type TaskPolicy } from './program.js';
|
package/dist/task.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { commandSlot } from './program.js';
|
|
2
|
-
import
|
|
2
|
+
import * as Cause from 'effect/Cause';
|
|
3
|
+
import * as Effect from 'effect/Effect';
|
|
4
|
+
import * as Option from 'effect/Option';
|
|
3
5
|
import * as AsyncResult from 'effect/unstable/reactivity/AsyncResult';
|
|
4
6
|
import { programView } from './component.js';
|
|
5
7
|
import { effectCommand, } from './program.js';
|
package/dist/tasks.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Snapshot } from './snapshot.js';
|
|
2
2
|
import type { ModelOwner, TaskPolicy } from './owner.js';
|
|
3
|
-
import
|
|
3
|
+
import * as Effect from 'effect/Effect';
|
|
4
4
|
import * as AsyncResult from 'effect/unstable/reactivity/AsyncResult';
|
|
5
5
|
import type { View } from './dom.js';
|
|
6
6
|
import { type CommandSlot, type Send, type RunningProgram } from './program.js';
|
package/dist/tasks.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Effect from 'effect/Effect';
|
|
2
|
+
import * as Option from 'effect/Option';
|
|
2
3
|
import * as AsyncResult from 'effect/unstable/reactivity/AsyncResult';
|
|
3
4
|
import { programView } from './component.js';
|
|
4
5
|
import { commandSlot, effectCommand, program, } from './program.js';
|
package/dist/testing.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Effect from 'effect/Effect';
|
|
2
2
|
import type { CommandSlot, Program, RunningProgram } from './program.js';
|
|
3
3
|
import { type UiRuntime } from './runtime.js';
|
|
4
4
|
/** Program inspection and controlled Effect execution with application-owned services. */
|
|
5
5
|
export interface ProgramDriver<M, Msg, R = never> extends Program<M, Msg> {
|
|
6
|
+
readonly close: RunningProgram<M, Msg>['close'];
|
|
6
7
|
readonly activeSlots: RunningProgram<M, Msg>['activeSlots'];
|
|
7
|
-
readonly awaitSlot: (slot: CommandSlot) =>
|
|
8
|
-
readonly awaitIdle: () =>
|
|
9
|
-
readonly run: <A, E>(effect: Effect.Effect<A, E, R>) =>
|
|
8
|
+
readonly awaitSlot: (slot: CommandSlot) => Effect.Effect<void>;
|
|
9
|
+
readonly awaitIdle: () => Effect.Effect<void>;
|
|
10
|
+
readonly run: <A, E>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E>;
|
|
10
11
|
}
|
|
11
12
|
export declare function programDriver<M, Msg>(source: RunningProgram<M, Msg>): ProgramDriver<M, Msg>;
|
|
12
13
|
export declare function programDriver<M, Msg, R>(source: RunningProgram<M, Msg>, runtime: UiRuntime<R>): ProgramDriver<M, Msg, R>;
|
package/dist/testing.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Cause from 'effect/Cause';
|
|
2
|
+
import * as Effect from 'effect/Effect';
|
|
2
3
|
import { defaultUiRuntime } from './runtime.js';
|
|
3
4
|
export function programDriver(source, runtime) {
|
|
4
5
|
return makeDriver(source, runtime ?? defaultUiRuntime);
|
|
@@ -9,10 +10,11 @@ function makeDriver(source, runtime) {
|
|
|
9
10
|
send: source.send,
|
|
10
11
|
subscribe: source.subscribe,
|
|
11
12
|
dispose: source.dispose,
|
|
13
|
+
close: source.close,
|
|
12
14
|
activeSlots: source.activeSlots,
|
|
13
15
|
awaitSlot: (slot) => source.awaitIdle(slot),
|
|
14
16
|
awaitIdle: () => source.awaitIdle(),
|
|
15
|
-
run:
|
|
17
|
+
run: runtime.provide,
|
|
16
18
|
};
|
|
17
19
|
}
|
|
18
20
|
/** A reusable controlled request, with cancellation visible to tests. No renderer or private messages. */
|
package/package.json
CHANGED
package/dist/intrinsic.d.ts
DELETED
package/dist/intrinsic.js
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import { compiledSlots } from './slotIdentity.js';
|
|
2
|
-
// Compiler implementation detail. An untyped receiver's method name is not
|
|
3
|
-
// evidence that it is a standard data operation. Validate its descriptor before
|
|
4
|
-
// invoking it, without running a user getter in the process.
|
|
5
|
-
const prototypes = [
|
|
6
|
-
Array.prototype,
|
|
7
|
-
String.prototype,
|
|
8
|
-
Number.prototype,
|
|
9
|
-
Boolean.prototype,
|
|
10
|
-
BigInt.prototype,
|
|
11
|
-
Function.prototype,
|
|
12
|
-
Date.prototype,
|
|
13
|
-
RegExp.prototype,
|
|
14
|
-
Map.prototype,
|
|
15
|
-
Set.prototype,
|
|
16
|
-
URL.prototype,
|
|
17
|
-
URLSearchParams.prototype,
|
|
18
|
-
Blob.prototype,
|
|
19
|
-
File.prototype,
|
|
20
|
-
Object.getPrototypeOf(Uint8Array.prototype),
|
|
21
|
-
Intl.DateTimeFormat.prototype,
|
|
22
|
-
Intl.NumberFormat.prototype,
|
|
23
|
-
Intl.Collator.prototype,
|
|
24
|
-
Intl.RelativeTimeFormat.prototype,
|
|
25
|
-
Intl.PluralRules.prototype,
|
|
26
|
-
Intl.ListFormat.prototype,
|
|
27
|
-
Intl.Segmenter.prototype,
|
|
28
|
-
];
|
|
29
|
-
const operations = new Map();
|
|
30
|
-
for (const prototype of prototypes) {
|
|
31
|
-
for (const [name, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(prototype))) {
|
|
32
|
-
if (name === 'constructor')
|
|
33
|
-
continue;
|
|
34
|
-
const entries = operations.get(name) ?? [];
|
|
35
|
-
entries.push(descriptor);
|
|
36
|
-
operations.set(name, entries);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
/** Preserve receiver identity and JavaScript call/optional-chain semantics. */
|
|
40
|
-
export function intrinsic(receiver, path, method) {
|
|
41
|
-
checkPath(receiver, path, 0, method);
|
|
42
|
-
return receiver;
|
|
43
|
-
}
|
|
44
|
-
function checkPath(target, path, index, method) {
|
|
45
|
-
if (target === null || target === undefined)
|
|
46
|
-
return;
|
|
47
|
-
if (index === path.length) {
|
|
48
|
-
checkIntrinsic(target, method);
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
const field = path[index];
|
|
52
|
-
if (field === null) {
|
|
53
|
-
if (Array.isArray(target)) {
|
|
54
|
-
for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(target))) {
|
|
55
|
-
if (!/^(0|[1-9]\d*)$/u.test(key))
|
|
56
|
-
continue;
|
|
57
|
-
if (!Object.hasOwn(descriptor, 'value'))
|
|
58
|
-
throw new Error('EffectWeb render data cannot use an array accessor. Pass immutable values.');
|
|
59
|
-
checkPath(descriptor.value, path, index + 1, method);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
else if (target instanceof Map) {
|
|
63
|
-
for (const value of Map.prototype.values.call(target))
|
|
64
|
-
checkPath(value, path, index + 1, method);
|
|
65
|
-
}
|
|
66
|
-
else if (target instanceof Set) {
|
|
67
|
-
for (const value of Set.prototype.values.call(target))
|
|
68
|
-
checkPath(value, path, index + 1, method);
|
|
69
|
-
}
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
let object = Object(target);
|
|
73
|
-
while (object) {
|
|
74
|
-
const descriptor = Object.getOwnPropertyDescriptor(object, field);
|
|
75
|
-
if (descriptor) {
|
|
76
|
-
if (Object.hasOwn(descriptor, 'value')) {
|
|
77
|
-
checkPath(descriptor.value, path, index + 1, method);
|
|
78
|
-
}
|
|
79
|
-
else if (descriptor.get &&
|
|
80
|
-
operations.get(field)?.some((operation) => operation.get === descriptor.get)) {
|
|
81
|
-
// Native getters are checked by identity before execution. File/Blob
|
|
82
|
-
// metadata and collection sizes expose data through readonly accessors.
|
|
83
|
-
checkPath(descriptor.get.call(target), path, index + 1, method);
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
throw new Error('EffectWeb render data cannot use an accessor to supply a standard data operation. Pass immutable data or a checked helper.');
|
|
87
|
-
}
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
object = Object.getPrototypeOf(object);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
function checkIntrinsic(receiver, method) {
|
|
94
|
-
if (receiver === null || receiver === undefined)
|
|
95
|
-
return;
|
|
96
|
-
if (method === '@slot') {
|
|
97
|
-
if (typeof receiver !== 'function' || !compiledSlots.has(receiver))
|
|
98
|
-
throw new Error('EffectWeb render callbacks must be compiled slots. Declare markup with slot(), or use a checked helper with an explicit purity contract.');
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
let object = Object(receiver);
|
|
102
|
-
while (object) {
|
|
103
|
-
const descriptor = Object.getOwnPropertyDescriptor(object, method);
|
|
104
|
-
if (descriptor) {
|
|
105
|
-
const known = operations
|
|
106
|
-
.get(method)
|
|
107
|
-
?.some((operation) => Object.hasOwn(descriptor, 'value')
|
|
108
|
-
? typeof descriptor.value === 'function' && descriptor.value === operation.value
|
|
109
|
-
: descriptor.get !== undefined &&
|
|
110
|
-
descriptor.get === operation.get &&
|
|
111
|
-
descriptor.set === undefined);
|
|
112
|
-
if (!known)
|
|
113
|
-
throw new Error(`EffectWeb cannot prove .${method} is a standard data operation. Use a checked local helper or an imported helper with a purity contract.`);
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
object = Object.getPrototypeOf(object);
|
|
117
|
-
}
|
|
118
|
-
// The original member call retains its own missing/optional-method behavior.
|
|
119
|
-
return;
|
|
120
|
-
}
|
package/dist/slotIdentity.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const compiledSlots: WeakSet<object>;
|
package/dist/slotIdentity.js
DELETED