effectweb 0.3.0 → 0.3.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/AsyncContent.js +1 -1
- package/dist/boundary.d.ts +11 -0
- package/dist/boundary.js +66 -0
- package/dist/cache-internals.d.ts +4 -0
- package/dist/cache.d.ts +20 -4
- package/dist/cache.js +174 -25
- package/dist/component.d.ts +3 -0
- package/dist/component.js +70 -10
- package/dist/dom.d.ts +12 -4
- package/dist/dom.js +38 -20
- package/dist/effectEvent.d.ts +2 -1
- package/dist/effectEvent.js +4 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.js +5 -2
- package/dist/infinite-query.d.ts +42 -0
- package/dist/infinite-query.js +150 -0
- package/dist/intrinsic.d.ts +2 -0
- package/dist/intrinsic.js +120 -0
- package/dist/keyed-tasks.d.ts +29 -0
- package/dist/keyed-tasks.js +97 -0
- package/dist/lazy.js +9 -1
- package/dist/mount.d.ts +3 -1
- package/dist/mount.js +29 -11
- package/dist/owner.d.ts +3 -1
- package/dist/owner.js +39 -3
- package/dist/pages.d.ts +15 -14
- package/dist/pages.js +6 -4
- package/dist/program.d.ts +10 -0
- package/dist/program.js +71 -24
- package/dist/query-internals.d.ts +4 -2
- package/dist/query.d.ts +6 -0
- package/dist/query.js +7 -1
- package/dist/session.js +13 -4
- package/dist/settlement.d.ts +7 -0
- package/dist/settlement.js +27 -0
- package/dist/sharing.js +16 -13
- package/dist/slotIdentity.d.ts +1 -0
- package/dist/slotIdentity.js +2 -0
- package/dist/snapshot.js +32 -24
- package/dist/tasks.js +1 -0
- package/package.json +9 -1
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Internal completion accounting, including reentrant acquisition before a fiber is available. */
|
|
2
|
+
export class Settlement {
|
|
3
|
+
pending = 0;
|
|
4
|
+
waiters = [];
|
|
5
|
+
begin() {
|
|
6
|
+
this.pending++;
|
|
7
|
+
let finished = false;
|
|
8
|
+
return () => {
|
|
9
|
+
if (finished)
|
|
10
|
+
return;
|
|
11
|
+
finished = true;
|
|
12
|
+
if (--this.pending)
|
|
13
|
+
return;
|
|
14
|
+
for (const done of this.waiters)
|
|
15
|
+
done();
|
|
16
|
+
this.waiters.length = 0;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
wait() {
|
|
20
|
+
return new Promise((done) => {
|
|
21
|
+
if (this.pending)
|
|
22
|
+
this.waiters.push(done);
|
|
23
|
+
else
|
|
24
|
+
done();
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
package/dist/sharing.js
CHANGED
|
@@ -60,28 +60,31 @@ function share(previous, next, fields) {
|
|
|
60
60
|
oldKeys.some((key) => !Object.hasOwn(Object.getOwnPropertyDescriptor(previous, key), 'value')))
|
|
61
61
|
return next;
|
|
62
62
|
let equal = keys.length === oldKeys.length && (!array || value.length === old.length);
|
|
63
|
-
let
|
|
64
|
-
const shared = array ? [] : {};
|
|
65
|
-
if (array)
|
|
66
|
-
shared.length = value.length;
|
|
63
|
+
let changed;
|
|
67
64
|
for (const key of keys) {
|
|
68
65
|
const custom = fields && Object.hasOwn(fields, key) ? fields[key] : undefined;
|
|
69
66
|
const item = custom && Object.hasOwn(old, key)
|
|
70
67
|
? custom(old[key], value[key])
|
|
71
68
|
: share(Object.hasOwn(old, key) ? old[key] : undefined, value[key], undefined);
|
|
72
|
-
// Define an own data property, including __proto__, without invoking setters.
|
|
73
|
-
Object.defineProperty(shared, key, {
|
|
74
|
-
value: item,
|
|
75
|
-
writable: true,
|
|
76
|
-
enumerable: true,
|
|
77
|
-
configurable: true,
|
|
78
|
-
});
|
|
79
69
|
if (!Object.hasOwn(old, key) || !Object.is(item, old[key]))
|
|
80
70
|
equal = false;
|
|
81
71
|
if (!Object.is(item, value[key]))
|
|
82
|
-
|
|
72
|
+
(changed ??= new Map()).set(key, item);
|
|
73
|
+
}
|
|
74
|
+
let result = equal ? previous : next;
|
|
75
|
+
if (!equal && changed) {
|
|
76
|
+
const shared = array ? [] : {};
|
|
77
|
+
if (array)
|
|
78
|
+
shared.length = value.length;
|
|
79
|
+
for (const key of keys)
|
|
80
|
+
Object.defineProperty(shared, key, {
|
|
81
|
+
value: changed.has(key) ? changed.get(key) : value[key],
|
|
82
|
+
writable: true,
|
|
83
|
+
enumerable: true,
|
|
84
|
+
configurable: true,
|
|
85
|
+
});
|
|
86
|
+
result = shared;
|
|
83
87
|
}
|
|
84
|
-
const result = equal ? previous : unchangedNext ? next : shared;
|
|
85
88
|
if (fields)
|
|
86
89
|
return result;
|
|
87
90
|
if (!pairs) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const compiledSlots: WeakSet<object>;
|
package/dist/snapshot.js
CHANGED
|
@@ -2,29 +2,37 @@ import { isAsyncResult } from 'effect/unstable/reactivity/AsyncResult';
|
|
|
2
2
|
const checked = new WeakSet();
|
|
3
3
|
/** Protect published plain data in every build. Opaque objects keep their own lifecycle. */
|
|
4
4
|
export function protectSnapshot(value) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
5
|
+
const seen = new Set();
|
|
6
|
+
const plain = [];
|
|
7
|
+
const validate = (item) => {
|
|
8
|
+
if (!item || typeof item !== 'object' || checked.has(item) || seen.has(item))
|
|
9
|
+
return;
|
|
10
|
+
seen.add(item);
|
|
11
|
+
// Effect wrappers remain opaque, but their successful UI data is plain data.
|
|
12
|
+
if (isAsyncResult(item)) {
|
|
13
|
+
if (item._tag === 'Success')
|
|
14
|
+
validate(item.value);
|
|
15
|
+
else if (item._tag === 'Failure' && item.previousSuccess._tag === 'Some')
|
|
16
|
+
validate(item.previousSuccess.value);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const prototype = Object.getPrototypeOf(item);
|
|
20
|
+
if (!Array.isArray(item) && prototype !== Object.prototype && prototype !== null)
|
|
21
|
+
return;
|
|
22
|
+
for (const key of Reflect.ownKeys(item)) {
|
|
23
|
+
const descriptor = Object.getOwnPropertyDescriptor(item, key);
|
|
24
|
+
if (!Object.hasOwn(descriptor, 'value'))
|
|
25
|
+
throw new Error(`Snapshot data cannot contain an accessor (${String(key)}). Materialize its value before publication; keep services in opaque instances.`);
|
|
26
|
+
validate(descriptor.value);
|
|
27
|
+
}
|
|
28
|
+
plain.push(item);
|
|
29
|
+
};
|
|
30
|
+
// Validate the complete graph before caching any proof. A rejected cyclic graph
|
|
31
|
+
// must not make a later publication skip validation through a previously seen child.
|
|
32
|
+
validate(value);
|
|
33
|
+
for (const item of plain)
|
|
34
|
+
Object.freeze(item);
|
|
35
|
+
for (const item of seen)
|
|
36
|
+
checked.add(item);
|
|
29
37
|
return value;
|
|
30
38
|
}
|
package/dist/tasks.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "effectweb",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Immutable Effect models and compiled JSX with direct DOM rendering",
|
|
5
5
|
"homepage": "https://github.com/DerpyCrabs/EffectWeb",
|
|
6
6
|
"bugs": {
|
|
@@ -127,6 +127,14 @@
|
|
|
127
127
|
"./http": {
|
|
128
128
|
"types": "./dist/http.d.ts",
|
|
129
129
|
"import": "./dist/http.js"
|
|
130
|
+
},
|
|
131
|
+
"./infinite-query": {
|
|
132
|
+
"types": "./dist/infinite-query.d.ts",
|
|
133
|
+
"import": "./dist/infinite-query.js"
|
|
134
|
+
},
|
|
135
|
+
"./keyed-tasks": {
|
|
136
|
+
"types": "./dist/keyed-tasks.d.ts",
|
|
137
|
+
"import": "./dist/keyed-tasks.js"
|
|
130
138
|
}
|
|
131
139
|
},
|
|
132
140
|
"publishConfig": {
|