@peerbit/document 15.0.13 → 15.0.15
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/src/callback-detachment.d.ts +19 -0
- package/dist/src/callback-detachment.d.ts.map +1 -0
- package/dist/src/callback-detachment.js +605 -0
- package/dist/src/callback-detachment.js.map +1 -0
- package/dist/src/domain.d.ts.map +1 -1
- package/dist/src/domain.js +5 -3
- package/dist/src/domain.js.map +1 -1
- package/dist/src/program.d.ts +5 -0
- package/dist/src/program.d.ts.map +1 -1
- package/dist/src/program.js +149 -40
- package/dist/src/program.js.map +1 -1
- package/dist/src/search.d.ts +2 -0
- package/dist/src/search.d.ts.map +1 -1
- package/dist/src/search.js +36 -6
- package/dist/src/search.js.map +1 -1
- package/dist/src/transform.d.ts +2 -0
- package/dist/src/transform.d.ts.map +1 -1
- package/dist/src/transform.js +4 -0
- package/dist/src/transform.js.map +1 -1
- package/package.json +9 -9
- package/src/callback-detachment.ts +848 -0
- package/src/domain.ts +10 -3
- package/src/program.ts +233 -49
- package/src/search.ts +49 -5
- package/src/transform.ts +7 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { PublicSignKey } from "@peerbit/crypto";
|
|
2
|
+
import { Entry } from "@peerbit/log";
|
|
3
|
+
import { type Operation } from "./operation.js";
|
|
4
|
+
/**
|
|
5
|
+
* Borsh byte fields are input-buffer views. Clone only fields that can expose
|
|
6
|
+
* verified operation bytes while retaining the operation's exact prototype,
|
|
7
|
+
* subclass fields, symbols, and property descriptors.
|
|
8
|
+
*/
|
|
9
|
+
export declare const detachOperationBytes: <T extends Operation>(operation: T) => T;
|
|
10
|
+
export declare const detachCanPerformCallbackProperties: <T extends {
|
|
11
|
+
operation: Operation;
|
|
12
|
+
entry: Entry<any>;
|
|
13
|
+
}>(properties: T) => T;
|
|
14
|
+
export declare const detachEntryPayloadForCallback: <T>(entry: Entry<T>) => Entry<T>;
|
|
15
|
+
/** Detach full, shallow, and replicated entries at document callback edges. */
|
|
16
|
+
export declare const detachEntryForCallback: <T>(entry: T) => T;
|
|
17
|
+
/** Give arbitrary document transforms signer objects they cannot retain/mutate. */
|
|
18
|
+
export declare const detachPublicKeysForCallback: (keys: readonly PublicSignKey[]) => PublicSignKey[];
|
|
19
|
+
//# sourceMappingURL=callback-detachment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callback-detachment.d.ts","sourceRoot":"","sources":["../../src/callback-detachment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAoB,MAAM,iBAAiB,CAAC;AAEvE,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,EAGN,KAAK,SAAS,EAGd,MAAM,gBAAgB,CAAC;AA8YxB;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,GAAI,CAAC,SAAS,SAAS,EAAE,WAAW,CAAC,KAAG,CAgDxE,CAAC;AAkGF,eAAO,MAAM,kCAAkC,GAC9C,CAAC,SAAS;IAAE,SAAS,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAA;CAAE,EAErD,YAAY,CAAC,KACX,CAUF,CAAC;AA4PF,eAAO,MAAM,6BAA6B,GAAI,CAAC,EAAE,OAAO,KAAK,CAAC,CAAC,CAAC,KAAG,KAAK,CAAC,CAAC,CAMzE,CAAC;AAEF,+EAA+E;AAC/E,eAAO,MAAM,sBAAsB,GAAI,CAAC,EAAE,OAAO,CAAC,KAAG,CASpD,CAAC;AAEF,mFAAmF;AACnF,eAAO,MAAM,2BAA2B,GACvC,MAAM,SAAS,aAAa,EAAE,KAC5B,aAAa,EAA2D,CAAC"}
|
|
@@ -0,0 +1,605 @@
|
|
|
1
|
+
import * as indexerTypes from "@peerbit/indexer-interface";
|
|
2
|
+
import { Entry } from "@peerbit/log";
|
|
3
|
+
import { DeleteByStringKeyOperation, DeleteOperation, PutOperation, PutWithKeyOperation, } from "./operation.js";
|
|
4
|
+
const isPromiseLike = (value) => !!value &&
|
|
5
|
+
(typeof value === "object" || typeof value === "function") &&
|
|
6
|
+
typeof value.then === "function";
|
|
7
|
+
const mapMaybePromise = (value, map) => (isPromiseLike(value) ? value.then(map) : map(value));
|
|
8
|
+
const copyOptionalBytes = (bytes) => bytes == null ? undefined : new Uint8Array(bytes);
|
|
9
|
+
const preserveArrayIntegrity = (source, copy) => {
|
|
10
|
+
if (Object.isFrozen(source)) {
|
|
11
|
+
Object.freeze(copy);
|
|
12
|
+
}
|
|
13
|
+
else if (Object.isSealed(source)) {
|
|
14
|
+
Object.seal(copy);
|
|
15
|
+
}
|
|
16
|
+
else if (!Object.isExtensible(source)) {
|
|
17
|
+
Object.preventExtensions(copy);
|
|
18
|
+
}
|
|
19
|
+
return copy;
|
|
20
|
+
};
|
|
21
|
+
const detachArray = (values, detach = (value) => value) => preserveArrayIntegrity(values, values.map(detach));
|
|
22
|
+
const getInheritedPropertyDescriptor = (value, key) => {
|
|
23
|
+
let prototype = Object.getPrototypeOf(value);
|
|
24
|
+
while (prototype) {
|
|
25
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(prototype, key);
|
|
26
|
+
if (descriptor) {
|
|
27
|
+
return descriptor;
|
|
28
|
+
}
|
|
29
|
+
prototype = Object.getPrototypeOf(prototype);
|
|
30
|
+
}
|
|
31
|
+
return undefined;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Clone an object without resolving selected nested values. For normal
|
|
35
|
+
* objects the selected fields become callback-local lazy accessors. The clone
|
|
36
|
+
* receives the source's frozen/sealed/non-extensible state only after those
|
|
37
|
+
* accessors are installed, so a no-touch callback never resolves lazy source
|
|
38
|
+
* fields.
|
|
39
|
+
*/
|
|
40
|
+
const cloneWithLazyProperties = (value, factories) => {
|
|
41
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
42
|
+
const extensible = Object.isExtensible(value);
|
|
43
|
+
for (const [key, factory] of factories) {
|
|
44
|
+
const ownDescriptor = descriptors[key];
|
|
45
|
+
const descriptor = ownDescriptor ?? getInheritedPropertyDescriptor(value, key);
|
|
46
|
+
let resolved = false;
|
|
47
|
+
let detachedValue;
|
|
48
|
+
const writable = descriptor
|
|
49
|
+
? (ownDescriptor != null || extensible) &&
|
|
50
|
+
("value" in descriptor
|
|
51
|
+
? descriptor.writable !== false
|
|
52
|
+
: descriptor.set != null)
|
|
53
|
+
: extensible;
|
|
54
|
+
descriptors[key] = {
|
|
55
|
+
configurable: descriptor?.configurable ?? true,
|
|
56
|
+
enumerable: descriptor?.enumerable ?? true,
|
|
57
|
+
get() {
|
|
58
|
+
if (!resolved) {
|
|
59
|
+
detachedValue = factory();
|
|
60
|
+
resolved = true;
|
|
61
|
+
}
|
|
62
|
+
return detachedValue;
|
|
63
|
+
},
|
|
64
|
+
...(writable
|
|
65
|
+
? {
|
|
66
|
+
set(nextValue) {
|
|
67
|
+
detachedValue = nextValue;
|
|
68
|
+
resolved = true;
|
|
69
|
+
},
|
|
70
|
+
}
|
|
71
|
+
: {}),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
const clone = Object.create(Object.getPrototypeOf(value), descriptors);
|
|
75
|
+
if (Object.isFrozen(value)) {
|
|
76
|
+
Object.freeze(clone);
|
|
77
|
+
}
|
|
78
|
+
else if (Object.isSealed(value)) {
|
|
79
|
+
Object.seal(clone);
|
|
80
|
+
}
|
|
81
|
+
else if (!Object.isExtensible(value)) {
|
|
82
|
+
Object.preventExtensions(clone);
|
|
83
|
+
}
|
|
84
|
+
return clone;
|
|
85
|
+
};
|
|
86
|
+
const addOwnByteFactories = (value, factories) => {
|
|
87
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
88
|
+
for (const key of Reflect.ownKeys(descriptors)) {
|
|
89
|
+
const descriptor = descriptors[key];
|
|
90
|
+
if (descriptor && "value" in descriptor) {
|
|
91
|
+
const bytes = descriptor.value;
|
|
92
|
+
if (bytes instanceof Uint8Array) {
|
|
93
|
+
factories.set(key, () => new Uint8Array(bytes));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
const addOwnArrayFactories = (value, factories) => {
|
|
99
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
100
|
+
for (const key of Reflect.ownKeys(descriptors)) {
|
|
101
|
+
const descriptor = descriptors[key];
|
|
102
|
+
if (descriptor &&
|
|
103
|
+
"value" in descriptor &&
|
|
104
|
+
Array.isArray(descriptor.value)) {
|
|
105
|
+
const array = descriptor.value;
|
|
106
|
+
factories.set(key, () => detachArray(array, (item) => item instanceof Uint8Array ? new Uint8Array(item) : item));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
const detachedCallbackEntryLikes = new WeakSet();
|
|
111
|
+
const createEntryDetachmentContext = () => {
|
|
112
|
+
let metadata;
|
|
113
|
+
let clocks;
|
|
114
|
+
let timestamps;
|
|
115
|
+
let signatures;
|
|
116
|
+
let publicKeys;
|
|
117
|
+
let entryLikes;
|
|
118
|
+
let arrays;
|
|
119
|
+
const detachValues = (values, detach = (value) => value) => {
|
|
120
|
+
const cached = arrays?.get(values);
|
|
121
|
+
if (cached) {
|
|
122
|
+
return cached;
|
|
123
|
+
}
|
|
124
|
+
const clone = detachArray(values, detach);
|
|
125
|
+
(arrays ??= new WeakMap()).set(values, clone);
|
|
126
|
+
return clone;
|
|
127
|
+
};
|
|
128
|
+
const detachTimestamp = (value) => {
|
|
129
|
+
if (!value || typeof value !== "object") {
|
|
130
|
+
return value;
|
|
131
|
+
}
|
|
132
|
+
const cached = timestamps?.get(value);
|
|
133
|
+
if (cached) {
|
|
134
|
+
return cached;
|
|
135
|
+
}
|
|
136
|
+
const factories = new Map();
|
|
137
|
+
addOwnByteFactories(value, factories);
|
|
138
|
+
const clone = cloneWithLazyProperties(value, factories);
|
|
139
|
+
(timestamps ??= new WeakMap()).set(value, clone);
|
|
140
|
+
return clone;
|
|
141
|
+
};
|
|
142
|
+
const detachClock = (value) => {
|
|
143
|
+
if (!value || typeof value !== "object") {
|
|
144
|
+
return value;
|
|
145
|
+
}
|
|
146
|
+
const cached = clocks?.get(value);
|
|
147
|
+
if (cached) {
|
|
148
|
+
return cached;
|
|
149
|
+
}
|
|
150
|
+
const factories = new Map();
|
|
151
|
+
addOwnByteFactories(value, factories);
|
|
152
|
+
if (Reflect.has(value, "id") && !factories.has("id")) {
|
|
153
|
+
factories.set("id", () => copyOptionalBytes(Reflect.get(value, "id", value)));
|
|
154
|
+
}
|
|
155
|
+
if (Reflect.has(value, "timestamp")) {
|
|
156
|
+
factories.set("timestamp", () => detachTimestamp(Reflect.get(value, "timestamp", value)));
|
|
157
|
+
}
|
|
158
|
+
const clone = cloneWithLazyProperties(value, factories);
|
|
159
|
+
(clocks ??= new WeakMap()).set(value, clone);
|
|
160
|
+
return clone;
|
|
161
|
+
};
|
|
162
|
+
const detachMeta = (value) => {
|
|
163
|
+
if (!value || typeof value !== "object") {
|
|
164
|
+
return value;
|
|
165
|
+
}
|
|
166
|
+
const cached = metadata?.get(value);
|
|
167
|
+
if (cached) {
|
|
168
|
+
return cached;
|
|
169
|
+
}
|
|
170
|
+
const factories = new Map();
|
|
171
|
+
addOwnByteFactories(value, factories);
|
|
172
|
+
if (Reflect.has(value, "data") && !factories.has("data")) {
|
|
173
|
+
factories.set("data", () => copyOptionalBytes(Reflect.get(value, "data", value)));
|
|
174
|
+
}
|
|
175
|
+
if (Reflect.has(value, "clock")) {
|
|
176
|
+
factories.set("clock", () => detachClock(Reflect.get(value, "clock", value)));
|
|
177
|
+
}
|
|
178
|
+
if (Reflect.has(value, "next")) {
|
|
179
|
+
factories.set("next", () => {
|
|
180
|
+
const next = Reflect.get(value, "next", value);
|
|
181
|
+
return Array.isArray(next) ? detachValues(next) : next;
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
const clone = cloneWithLazyProperties(value, factories);
|
|
185
|
+
(metadata ??= new WeakMap()).set(value, clone);
|
|
186
|
+
return clone;
|
|
187
|
+
};
|
|
188
|
+
const detachPublicKey = (value) => {
|
|
189
|
+
if (!value || typeof value !== "object") {
|
|
190
|
+
return value;
|
|
191
|
+
}
|
|
192
|
+
const cached = publicKeys?.get(value);
|
|
193
|
+
if (cached) {
|
|
194
|
+
return cached;
|
|
195
|
+
}
|
|
196
|
+
const factories = new Map();
|
|
197
|
+
addOwnByteFactories(value, factories);
|
|
198
|
+
const clone = cloneWithLazyProperties(value, factories);
|
|
199
|
+
(publicKeys ??= new WeakMap()).set(value, clone);
|
|
200
|
+
return clone;
|
|
201
|
+
};
|
|
202
|
+
const detachSignature = (value) => {
|
|
203
|
+
if (!value || typeof value !== "object") {
|
|
204
|
+
return value;
|
|
205
|
+
}
|
|
206
|
+
const cached = signatures?.get(value);
|
|
207
|
+
if (cached) {
|
|
208
|
+
return cached;
|
|
209
|
+
}
|
|
210
|
+
const factories = new Map();
|
|
211
|
+
addOwnByteFactories(value, factories);
|
|
212
|
+
if (Reflect.has(value, "publicKey")) {
|
|
213
|
+
factories.set("publicKey", () => detachPublicKey(Reflect.get(value, "publicKey", value)));
|
|
214
|
+
}
|
|
215
|
+
const clone = cloneWithLazyProperties(value, factories);
|
|
216
|
+
(signatures ??= new WeakMap()).set(value, clone);
|
|
217
|
+
return clone;
|
|
218
|
+
};
|
|
219
|
+
const detachSignatures = (values) => detachValues(values, detachSignature);
|
|
220
|
+
const detachPublicKeys = (values) => detachValues(values, detachPublicKey);
|
|
221
|
+
const detachEntryLike = (value) => {
|
|
222
|
+
if (detachedCallbackEntryLikes.has(value)) {
|
|
223
|
+
return value;
|
|
224
|
+
}
|
|
225
|
+
const cached = entryLikes?.get(value);
|
|
226
|
+
if (cached) {
|
|
227
|
+
return cached;
|
|
228
|
+
}
|
|
229
|
+
const factories = new Map();
|
|
230
|
+
addOwnByteFactories(value, factories);
|
|
231
|
+
addOwnArrayFactories(value, factories);
|
|
232
|
+
if (Reflect.has(value, "meta")) {
|
|
233
|
+
factories.set("meta", () => detachMeta(Reflect.get(value, "meta", value)));
|
|
234
|
+
}
|
|
235
|
+
for (const methodName of ["getMetaBytes", "getHashDigestBytes"]) {
|
|
236
|
+
const method = Reflect.get(value, methodName, value);
|
|
237
|
+
if (typeof method === "function") {
|
|
238
|
+
factories.set(methodName, () => (...args) => mapMaybePromise(Reflect.apply(method, value, args), copyOptionalBytes));
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
const clone = cloneWithLazyProperties(value, factories);
|
|
242
|
+
(entryLikes ??= new WeakMap()).set(value, clone);
|
|
243
|
+
detachedCallbackEntryLikes.add(clone);
|
|
244
|
+
return clone;
|
|
245
|
+
};
|
|
246
|
+
return {
|
|
247
|
+
detachArray: detachValues,
|
|
248
|
+
detachClock,
|
|
249
|
+
detachEntryLike,
|
|
250
|
+
detachMeta,
|
|
251
|
+
detachPublicKeys,
|
|
252
|
+
detachSignatures,
|
|
253
|
+
};
|
|
254
|
+
};
|
|
255
|
+
const detachPreparedAppendJoinFactsForCallback = (facts, canonicalEntry, callbackEntry, getContext) => {
|
|
256
|
+
const factories = new Map();
|
|
257
|
+
addOwnByteFactories(facts, factories);
|
|
258
|
+
if (Reflect.has(facts, "bytes")) {
|
|
259
|
+
factories.set("bytes", () => copyOptionalBytes(Reflect.get(facts, "bytes", facts)));
|
|
260
|
+
}
|
|
261
|
+
if (Reflect.has(facts, "meta")) {
|
|
262
|
+
factories.set("meta", () => getContext().detachMeta(Reflect.get(facts, "meta", facts)));
|
|
263
|
+
}
|
|
264
|
+
const getShallowEntry = Reflect.get(facts, "getShallowEntry", facts);
|
|
265
|
+
if (typeof getShallowEntry === "function") {
|
|
266
|
+
factories.set("getShallowEntry", () => (...args) => {
|
|
267
|
+
const shallow = Reflect.apply(getShallowEntry, facts, args);
|
|
268
|
+
return shallow && typeof shallow === "object"
|
|
269
|
+
? getContext().detachEntryLike(shallow)
|
|
270
|
+
: shallow;
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
const materializeEntry = Reflect.get(facts, "materializeEntry", facts);
|
|
274
|
+
if (typeof materializeEntry === "function") {
|
|
275
|
+
factories.set("materializeEntry", () => (...args) => mapMaybePromise(Reflect.apply(materializeEntry, facts, args), (materialized) => materialized === canonicalEntry
|
|
276
|
+
? callbackEntry
|
|
277
|
+
: materialized instanceof Entry
|
|
278
|
+
? detachEntryPayloadForCallbackWithContext(materialized, getContext)
|
|
279
|
+
: materialized && typeof materialized === "object"
|
|
280
|
+
? getContext().detachEntryLike(materialized)
|
|
281
|
+
: materialized));
|
|
282
|
+
}
|
|
283
|
+
return cloneWithLazyProperties(facts, factories);
|
|
284
|
+
};
|
|
285
|
+
/**
|
|
286
|
+
* Borsh byte fields are input-buffer views. Clone only fields that can expose
|
|
287
|
+
* verified operation bytes while retaining the operation's exact prototype,
|
|
288
|
+
* subclass fields, symbols, and property descriptors.
|
|
289
|
+
*/
|
|
290
|
+
export const detachOperationBytes = (operation) => {
|
|
291
|
+
const cloneWithField = (value, key, replacement) => {
|
|
292
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
293
|
+
descriptors[key] = {
|
|
294
|
+
...descriptors[key],
|
|
295
|
+
value: replacement,
|
|
296
|
+
};
|
|
297
|
+
const clone = Object.create(Object.getPrototypeOf(value), descriptors);
|
|
298
|
+
if (!Object.isExtensible(value)) {
|
|
299
|
+
Object.preventExtensions(clone);
|
|
300
|
+
}
|
|
301
|
+
return clone;
|
|
302
|
+
};
|
|
303
|
+
if (operation instanceof PutWithKeyOperation) {
|
|
304
|
+
return cloneWithField(operation, "data", new Uint8Array(operation.data));
|
|
305
|
+
}
|
|
306
|
+
if (operation instanceof PutOperation) {
|
|
307
|
+
return cloneWithField(operation, "data", new Uint8Array(operation.data));
|
|
308
|
+
}
|
|
309
|
+
if (operation instanceof DeleteOperation) {
|
|
310
|
+
const key = cloneWithField(operation.key, "key", operation.key instanceof indexerTypes.Uint8ArrayKey
|
|
311
|
+
? new Uint8Array(operation.key.key)
|
|
312
|
+
: operation.key.key);
|
|
313
|
+
return cloneWithField(operation, "key", key);
|
|
314
|
+
}
|
|
315
|
+
if (operation instanceof DeleteByStringKeyOperation) {
|
|
316
|
+
return cloneWithField(operation, "key", operation.key);
|
|
317
|
+
}
|
|
318
|
+
return operation;
|
|
319
|
+
};
|
|
320
|
+
const lazyCallbackStates = new WeakMap();
|
|
321
|
+
const isLazyCallbackProperty = (property) => property === "operation" || property === "entry";
|
|
322
|
+
const settleCallbackProperty = (target, state, property) => {
|
|
323
|
+
state[`${property}Pending`] = false;
|
|
324
|
+
state[property] = undefined;
|
|
325
|
+
if (!state.operationPending && !state.entryPending) {
|
|
326
|
+
lazyCallbackStates.delete(target);
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
const materializeCallbackProperty = (target, property) => {
|
|
330
|
+
const state = lazyCallbackStates.get(target);
|
|
331
|
+
if (!state || !state[`${property}Pending`]) {
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
const value = property === "operation"
|
|
335
|
+
? detachOperationBytes(state.operation)
|
|
336
|
+
: detachEntryPayloadForCallback(state.entry);
|
|
337
|
+
Reflect.set(target, property, value, target);
|
|
338
|
+
settleCallbackProperty(target, state, property);
|
|
339
|
+
};
|
|
340
|
+
const lazyCallbackHandler = {
|
|
341
|
+
get(target, property, receiver) {
|
|
342
|
+
if (isLazyCallbackProperty(property)) {
|
|
343
|
+
materializeCallbackProperty(target, property);
|
|
344
|
+
}
|
|
345
|
+
return Reflect.get(target, property, receiver);
|
|
346
|
+
},
|
|
347
|
+
set(target, property, value) {
|
|
348
|
+
const updated = Reflect.set(target, property, value, target);
|
|
349
|
+
if (updated && isLazyCallbackProperty(property)) {
|
|
350
|
+
const state = lazyCallbackStates.get(target);
|
|
351
|
+
if (state) {
|
|
352
|
+
settleCallbackProperty(target, state, property);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return updated;
|
|
356
|
+
},
|
|
357
|
+
deleteProperty(target, property) {
|
|
358
|
+
const deleted = Reflect.deleteProperty(target, property);
|
|
359
|
+
if (deleted && isLazyCallbackProperty(property)) {
|
|
360
|
+
const state = lazyCallbackStates.get(target);
|
|
361
|
+
if (state) {
|
|
362
|
+
settleCallbackProperty(target, state, property);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
return deleted;
|
|
366
|
+
},
|
|
367
|
+
defineProperty(target, property, descriptor) {
|
|
368
|
+
if (isLazyCallbackProperty(property)) {
|
|
369
|
+
const replacesValue = "value" in descriptor || "get" in descriptor || "set" in descriptor;
|
|
370
|
+
if (!replacesValue) {
|
|
371
|
+
materializeCallbackProperty(target, property);
|
|
372
|
+
}
|
|
373
|
+
const defined = Reflect.defineProperty(target, property, descriptor);
|
|
374
|
+
if (defined && replacesValue) {
|
|
375
|
+
const state = lazyCallbackStates.get(target);
|
|
376
|
+
if (state) {
|
|
377
|
+
settleCallbackProperty(target, state, property);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return defined;
|
|
381
|
+
}
|
|
382
|
+
return Reflect.defineProperty(target, property, descriptor);
|
|
383
|
+
},
|
|
384
|
+
getOwnPropertyDescriptor(target, property) {
|
|
385
|
+
if (isLazyCallbackProperty(property)) {
|
|
386
|
+
materializeCallbackProperty(target, property);
|
|
387
|
+
}
|
|
388
|
+
return Reflect.getOwnPropertyDescriptor(target, property);
|
|
389
|
+
},
|
|
390
|
+
};
|
|
391
|
+
export const detachCanPerformCallbackProperties = (properties) => {
|
|
392
|
+
lazyCallbackStates.set(properties, {
|
|
393
|
+
operation: properties.operation,
|
|
394
|
+
entry: properties.entry,
|
|
395
|
+
operationPending: true,
|
|
396
|
+
entryPending: true,
|
|
397
|
+
});
|
|
398
|
+
Reflect.set(properties, "operation", undefined, properties);
|
|
399
|
+
Reflect.set(properties, "entry", undefined, properties);
|
|
400
|
+
return new Proxy(properties, lazyCallbackHandler);
|
|
401
|
+
};
|
|
402
|
+
/**
|
|
403
|
+
* Return an Entry view whose public accessors cannot expose verified payload,
|
|
404
|
+
* metadata, signature, public-key, or hash-digest buffers to application
|
|
405
|
+
* callbacks. Nested copies remain lazy, including metadata byte fields.
|
|
406
|
+
*/
|
|
407
|
+
const detachedCallbackEntries = new WeakSet();
|
|
408
|
+
const detachEntryPayloadForCallbackWithContext = (entry, getContext) => {
|
|
409
|
+
if (detachedCallbackEntries.has(entry)) {
|
|
410
|
+
return entry;
|
|
411
|
+
}
|
|
412
|
+
let detachedPayload;
|
|
413
|
+
let detachedMaterialized;
|
|
414
|
+
let callbackEntry;
|
|
415
|
+
const boundMethods = new Map();
|
|
416
|
+
const copyPayload = (payload) => {
|
|
417
|
+
if (detachedPayload) {
|
|
418
|
+
return detachedPayload;
|
|
419
|
+
}
|
|
420
|
+
const data = new Uint8Array(payload.data);
|
|
421
|
+
const descriptors = Object.getOwnPropertyDescriptors(payload);
|
|
422
|
+
descriptors.data = {
|
|
423
|
+
...descriptors.data,
|
|
424
|
+
value: data,
|
|
425
|
+
};
|
|
426
|
+
descriptors._value = {
|
|
427
|
+
configurable: true,
|
|
428
|
+
enumerable: false,
|
|
429
|
+
writable: true,
|
|
430
|
+
...descriptors._value,
|
|
431
|
+
value: payload.isDecoded ? payload.encoding.decoder(data) : undefined,
|
|
432
|
+
};
|
|
433
|
+
detachedPayload = Object.create(Object.getPrototypeOf(payload), descriptors);
|
|
434
|
+
if (!Object.isExtensible(payload)) {
|
|
435
|
+
Object.preventExtensions(detachedPayload);
|
|
436
|
+
}
|
|
437
|
+
return detachedPayload;
|
|
438
|
+
};
|
|
439
|
+
const getPayload = async () => {
|
|
440
|
+
const entryWithPayloadMethod = entry;
|
|
441
|
+
if (typeof entryWithPayloadMethod.getPayload === "function") {
|
|
442
|
+
return copyPayload(await entryWithPayloadMethod.getPayload.call(entry));
|
|
443
|
+
}
|
|
444
|
+
const materialized = entry.toMaterialized();
|
|
445
|
+
if (materialized !== entry) {
|
|
446
|
+
const materializedWithPayloadMethod = materialized;
|
|
447
|
+
if (typeof materializedWithPayloadMethod.getPayload === "function") {
|
|
448
|
+
return copyPayload(await materializedWithPayloadMethod.getPayload.call(materialized));
|
|
449
|
+
}
|
|
450
|
+
return copyPayload(materialized.payload);
|
|
451
|
+
}
|
|
452
|
+
return copyPayload(entry.payload);
|
|
453
|
+
};
|
|
454
|
+
const getPayloadValue = async () => {
|
|
455
|
+
const payload = await getPayload();
|
|
456
|
+
return payload.isDecoded ? payload.value : payload.getValue();
|
|
457
|
+
};
|
|
458
|
+
callbackEntry = new Proxy(entry, {
|
|
459
|
+
get(target, property) {
|
|
460
|
+
if (property === "payload") {
|
|
461
|
+
return copyPayload(entry.payload);
|
|
462
|
+
}
|
|
463
|
+
if (property === "meta") {
|
|
464
|
+
return getContext().detachMeta(Reflect.get(target, property, target));
|
|
465
|
+
}
|
|
466
|
+
if (property === "next") {
|
|
467
|
+
const next = Reflect.get(target, property, target);
|
|
468
|
+
return Array.isArray(next) ? getContext().detachArray(next) : next;
|
|
469
|
+
}
|
|
470
|
+
if (property === "signatures") {
|
|
471
|
+
return getContext().detachSignatures(Reflect.get(target, property, target));
|
|
472
|
+
}
|
|
473
|
+
if (property === "publicKeys") {
|
|
474
|
+
return getContext().detachPublicKeys(Reflect.get(target, property, target));
|
|
475
|
+
}
|
|
476
|
+
if (property === "getPayload" &&
|
|
477
|
+
typeof entry.getPayload ===
|
|
478
|
+
"function") {
|
|
479
|
+
return getPayload;
|
|
480
|
+
}
|
|
481
|
+
if (property === "getPayloadValue") {
|
|
482
|
+
return getPayloadValue;
|
|
483
|
+
}
|
|
484
|
+
if (property === "getMeta") {
|
|
485
|
+
const getMeta = Reflect.get(target, property, target);
|
|
486
|
+
if (typeof getMeta === "function") {
|
|
487
|
+
return (...args) => mapMaybePromise(Reflect.apply(getMeta, target, args), getContext().detachMeta);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
if (property === "getClock") {
|
|
491
|
+
const getClock = Reflect.get(target, property, target);
|
|
492
|
+
if (typeof getClock === "function") {
|
|
493
|
+
return (...args) => mapMaybePromise(Reflect.apply(getClock, target, args), getContext().detachClock);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
if (property === "getNext") {
|
|
497
|
+
const getNext = Reflect.get(target, property, target);
|
|
498
|
+
if (typeof getNext === "function") {
|
|
499
|
+
return (...args) => mapMaybePromise(Reflect.apply(getNext, target, args), (next) => Array.isArray(next) ? getContext().detachArray(next) : next);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
if (property === "getSignatures") {
|
|
503
|
+
const getSignatures = Reflect.get(target, property, target);
|
|
504
|
+
if (typeof getSignatures === "function") {
|
|
505
|
+
return (...args) => mapMaybePromise(Reflect.apply(getSignatures, target, args), getContext().detachSignatures);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
if (property === "getPublicKeys") {
|
|
509
|
+
const getPublicKeys = Reflect.get(target, property, target);
|
|
510
|
+
if (typeof getPublicKeys === "function") {
|
|
511
|
+
return (...args) => mapMaybePromise(Reflect.apply(getPublicKeys, target, args), getContext().detachPublicKeys);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
if (property === "getMetaBytes" || property === "getHashDigestBytes") {
|
|
515
|
+
const getBytes = Reflect.get(target, property, target);
|
|
516
|
+
if (typeof getBytes === "function") {
|
|
517
|
+
return (...args) => mapMaybePromise(Reflect.apply(getBytes, target, args), copyOptionalBytes);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
if (property === "__peerbitNext") {
|
|
521
|
+
const next = Reflect.get(target, property, target);
|
|
522
|
+
return Array.isArray(next) ? getContext().detachArray(next) : next;
|
|
523
|
+
}
|
|
524
|
+
if (property === "getStorageBytes") {
|
|
525
|
+
return () => new Uint8Array(entry.getStorageBytes());
|
|
526
|
+
}
|
|
527
|
+
if (property === "toShallow") {
|
|
528
|
+
const toShallow = Reflect.get(target, property, target);
|
|
529
|
+
if (typeof toShallow === "function") {
|
|
530
|
+
return (...args) => {
|
|
531
|
+
const shallow = Reflect.apply(toShallow, target, args);
|
|
532
|
+
return shallow && typeof shallow === "object"
|
|
533
|
+
? getContext().detachEntryLike(shallow)
|
|
534
|
+
: shallow;
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
if (property === "valueOf") {
|
|
539
|
+
return () => callbackEntry;
|
|
540
|
+
}
|
|
541
|
+
if (property === "toMaterialized") {
|
|
542
|
+
return () => {
|
|
543
|
+
const materialized = entry.toMaterialized();
|
|
544
|
+
if (materialized === entry) {
|
|
545
|
+
return callbackEntry;
|
|
546
|
+
}
|
|
547
|
+
return (detachedMaterialized ??=
|
|
548
|
+
detachEntryPayloadForCallbackWithContext(materialized, getContext));
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
if (property === "toSignable") {
|
|
552
|
+
return () => detachEntryPayloadForCallbackWithContext(entry.toSignable(), getContext);
|
|
553
|
+
}
|
|
554
|
+
if (property === "toPreparedAppendJoinFacts") {
|
|
555
|
+
const toPreparedAppendJoinFacts = Reflect.get(target, property, target);
|
|
556
|
+
if (typeof toPreparedAppendJoinFacts === "function") {
|
|
557
|
+
return (...args) => {
|
|
558
|
+
const facts = Reflect.apply(toPreparedAppendJoinFacts, target, args);
|
|
559
|
+
return facts && typeof facts === "object"
|
|
560
|
+
? detachPreparedAppendJoinFactsForCallback(facts, target, callbackEntry, getContext)
|
|
561
|
+
: facts;
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
if (property === "init") {
|
|
566
|
+
return (properties) => {
|
|
567
|
+
entry.init(properties);
|
|
568
|
+
return callbackEntry;
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
const value = Reflect.get(target, property, target);
|
|
572
|
+
if (property === "constructor" || typeof value !== "function") {
|
|
573
|
+
return value;
|
|
574
|
+
}
|
|
575
|
+
const existing = boundMethods.get(property);
|
|
576
|
+
if (existing && existing.source === value) {
|
|
577
|
+
return existing.bound;
|
|
578
|
+
}
|
|
579
|
+
const bound = value.bind(target);
|
|
580
|
+
boundMethods.set(property, { source: value, bound });
|
|
581
|
+
return bound;
|
|
582
|
+
},
|
|
583
|
+
set(target, property, value) {
|
|
584
|
+
return Reflect.set(target, property, value, target);
|
|
585
|
+
},
|
|
586
|
+
});
|
|
587
|
+
detachedCallbackEntries.add(callbackEntry);
|
|
588
|
+
return callbackEntry;
|
|
589
|
+
};
|
|
590
|
+
export const detachEntryPayloadForCallback = (entry) => {
|
|
591
|
+
let context;
|
|
592
|
+
return detachEntryPayloadForCallbackWithContext(entry, () => (context ??= createEntryDetachmentContext()));
|
|
593
|
+
};
|
|
594
|
+
/** Detach full, shallow, and replicated entries at document callback edges. */
|
|
595
|
+
export const detachEntryForCallback = (entry) => {
|
|
596
|
+
if (!entry || typeof entry !== "object") {
|
|
597
|
+
return entry;
|
|
598
|
+
}
|
|
599
|
+
return (entry instanceof Entry
|
|
600
|
+
? detachEntryPayloadForCallback(entry)
|
|
601
|
+
: createEntryDetachmentContext().detachEntryLike(entry));
|
|
602
|
+
};
|
|
603
|
+
/** Give arbitrary document transforms signer objects they cannot retain/mutate. */
|
|
604
|
+
export const detachPublicKeysForCallback = (keys) => createEntryDetachmentContext().detachPublicKeys(keys);
|
|
605
|
+
//# sourceMappingURL=callback-detachment.js.map
|