@skipruntime/core 0.0.16 → 0.0.18
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/api.d.ts +2 -2
- package/dist/src/api.d.ts.map +1 -1
- package/dist/src/binding.d.ts +20 -25
- package/dist/src/binding.d.ts.map +1 -1
- package/dist/src/binding.js.map +1 -1
- package/dist/src/index.d.ts +109 -35
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +529 -194
- package/dist/src/index.js.map +1 -1
- package/dist/src/internal.d.ts +0 -2
- package/dist/src/internal.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/api.ts +2 -2
- package/src/binding.ts +28 -63
- package/src/index.ts +714 -317
- package/src/internal.ts +0 -3
package/dist/src/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { deepFreeze, SkManaged, checkOrCloneParam, } from "../skiplang-json/inde
|
|
|
7
7
|
import { sknative } from "../skiplang-std/index.js";
|
|
8
8
|
import {} from "./api.js";
|
|
9
9
|
import { SkipClassNameError, SkipError, SkipNonUniqueValueError, SkipResourceInstanceInUseError, SkipUnknownCollectionError, } from "./errors.js";
|
|
10
|
-
import {
|
|
10
|
+
import {} from "./binding.js";
|
|
11
11
|
export * from "./api.js";
|
|
12
12
|
export * from "./errors.js";
|
|
13
13
|
function instantiateUserObject(what, ctor, params) {
|
|
@@ -17,7 +17,93 @@ function instantiateUserObject(what, ctor, params) {
|
|
|
17
17
|
if (!obj.constructor.name) {
|
|
18
18
|
throw new SkipClassNameError(`${what} classes must be defined at top-level.`);
|
|
19
19
|
}
|
|
20
|
-
return
|
|
20
|
+
return {
|
|
21
|
+
object: obj,
|
|
22
|
+
name: obj.constructor.name,
|
|
23
|
+
params: checkedParams,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export var LoadStatus;
|
|
27
|
+
(function (LoadStatus) {
|
|
28
|
+
LoadStatus[LoadStatus["Incompatible"] = 0] = "Incompatible";
|
|
29
|
+
LoadStatus[LoadStatus["Changed"] = 1] = "Changed";
|
|
30
|
+
LoadStatus[LoadStatus["Same"] = 2] = "Same";
|
|
31
|
+
})(LoadStatus || (LoadStatus = {}));
|
|
32
|
+
export class ServiceDefinition {
|
|
33
|
+
constructor(service, externals = new Map()) {
|
|
34
|
+
this.service = service;
|
|
35
|
+
this.externals = externals;
|
|
36
|
+
}
|
|
37
|
+
buildResource(name, parameters) {
|
|
38
|
+
const builder = this.service.resources[name];
|
|
39
|
+
if (!builder)
|
|
40
|
+
throw new Error(`Resource '${name}' not exist.`);
|
|
41
|
+
return new builder(parameters);
|
|
42
|
+
}
|
|
43
|
+
inputs() {
|
|
44
|
+
return this.service.initialData
|
|
45
|
+
? Object.keys(this.service.initialData)
|
|
46
|
+
: [];
|
|
47
|
+
}
|
|
48
|
+
resources() {
|
|
49
|
+
return Object.keys(this.service.resources);
|
|
50
|
+
}
|
|
51
|
+
initialData(name) {
|
|
52
|
+
if (!this.service.initialData)
|
|
53
|
+
throw new Error(`No initial data defined.`);
|
|
54
|
+
const data = this.service.initialData[name];
|
|
55
|
+
if (!data)
|
|
56
|
+
throw new Error(`Initial data '${name}' not exist.`);
|
|
57
|
+
return data;
|
|
58
|
+
}
|
|
59
|
+
createGraph(inputCollections, context) {
|
|
60
|
+
return this.service.createGraph(inputCollections, context);
|
|
61
|
+
}
|
|
62
|
+
subscribe(external, writer, instance, resource, params) {
|
|
63
|
+
if (!this.service.externalServices)
|
|
64
|
+
throw new Error(`No external services defined.`);
|
|
65
|
+
const supplier = this.service.externalServices[external];
|
|
66
|
+
if (!supplier)
|
|
67
|
+
throw new Error(`External services '${external}' not exist.`);
|
|
68
|
+
this.externals.set(`${external}/${instance}`, supplier);
|
|
69
|
+
// Ensure notification is made outside the current context update
|
|
70
|
+
return new Promise((resolve, reject) => {
|
|
71
|
+
setTimeout(() => {
|
|
72
|
+
supplier
|
|
73
|
+
.subscribe(instance, resource, params, {
|
|
74
|
+
update: writer.update.bind(writer),
|
|
75
|
+
error: (_) => { },
|
|
76
|
+
})
|
|
77
|
+
.then(resolve)
|
|
78
|
+
.catch(reject);
|
|
79
|
+
}, 0);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
unsubscribe(external, instance) {
|
|
83
|
+
if (!this.service.externalServices)
|
|
84
|
+
throw new Error(`No external services defined.`);
|
|
85
|
+
const supplier = this.externals.get(`${external}/${instance}`);
|
|
86
|
+
if (!supplier)
|
|
87
|
+
throw new Error(`External services '${external}/${instance}' not exist.`);
|
|
88
|
+
supplier.unsubscribe(instance);
|
|
89
|
+
this.externals.delete(`${external}/${instance}`);
|
|
90
|
+
}
|
|
91
|
+
async shutdown() {
|
|
92
|
+
const promises = [];
|
|
93
|
+
const uniqueServices = new Set(this.externals.values());
|
|
94
|
+
if (this.service.externalServices) {
|
|
95
|
+
for (const es of Object.values(this.service.externalServices)) {
|
|
96
|
+
uniqueServices.add(es);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
for (const es of uniqueServices) {
|
|
100
|
+
promises.push(es.shutdown());
|
|
101
|
+
}
|
|
102
|
+
await Promise.all(promises);
|
|
103
|
+
}
|
|
104
|
+
derive(service) {
|
|
105
|
+
return new ServiceDefinition(service, new Map(this.externals));
|
|
106
|
+
}
|
|
21
107
|
}
|
|
22
108
|
class Handles {
|
|
23
109
|
constructor() {
|
|
@@ -61,15 +147,6 @@ export class Stack {
|
|
|
61
147
|
this.stack.pop();
|
|
62
148
|
}
|
|
63
149
|
}
|
|
64
|
-
export class Refs {
|
|
65
|
-
constructor(binding, skjson, handles, needGC, runWithGC) {
|
|
66
|
-
this.binding = binding;
|
|
67
|
-
this.skjson = skjson;
|
|
68
|
-
this.handles = handles;
|
|
69
|
-
this.needGC = needGC;
|
|
70
|
-
this.runWithGC = runWithGC;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
150
|
class LazyCollectionImpl extends SkManaged {
|
|
74
151
|
constructor(lazyCollection, refs) {
|
|
75
152
|
super();
|
|
@@ -78,7 +155,9 @@ class LazyCollectionImpl extends SkManaged {
|
|
|
78
155
|
Object.freeze(this);
|
|
79
156
|
}
|
|
80
157
|
getArray(key) {
|
|
81
|
-
return this.refs
|
|
158
|
+
return this.refs
|
|
159
|
+
.json()
|
|
160
|
+
.importJSON(this.refs.binding.SkipRuntime_LazyCollection__getArray(this.lazyCollection, this.refs.json().exportJSON(key)));
|
|
82
161
|
}
|
|
83
162
|
getUnique(key, _default) {
|
|
84
163
|
const values = this.getArray(key);
|
|
@@ -107,7 +186,9 @@ class EagerCollectionImpl extends SkManaged {
|
|
|
107
186
|
Object.freeze(this);
|
|
108
187
|
}
|
|
109
188
|
getArray(key) {
|
|
110
|
-
return this.refs
|
|
189
|
+
return this.refs
|
|
190
|
+
.json()
|
|
191
|
+
.importJSON(this.refs.binding.SkipRuntime_Collection__getArray(this.collection, this.refs.json().exportJSON(key)));
|
|
111
192
|
}
|
|
112
193
|
getUnique(key, _default) {
|
|
113
194
|
const values = this.getArray(key);
|
|
@@ -128,7 +209,7 @@ class EagerCollectionImpl extends SkManaged {
|
|
|
128
209
|
return this.slices([start, end]);
|
|
129
210
|
}
|
|
130
211
|
slices(...ranges) {
|
|
131
|
-
const skcollection = this.refs.binding.SkipRuntime_Collection__slice(this.collection, this.refs.
|
|
212
|
+
const skcollection = this.refs.binding.SkipRuntime_Collection__slice(this.collection, this.refs.json().exportJSON(ranges));
|
|
132
213
|
return this.derive(skcollection);
|
|
133
214
|
}
|
|
134
215
|
take(limit) {
|
|
@@ -146,28 +227,30 @@ class EagerCollectionImpl extends SkManaged {
|
|
|
146
227
|
const mapperObj = instantiateUserObject("Mapper", mapper, mapperParams);
|
|
147
228
|
const reducerObj = instantiateUserObject("Reducer", reducer, reducerParams);
|
|
148
229
|
const skmapper = this.refs.binding.SkipRuntime_createMapper(this.refs.handles.register(mapperObj));
|
|
149
|
-
if (sknative in reducerObj &&
|
|
150
|
-
|
|
230
|
+
if (sknative in reducerObj.object &&
|
|
231
|
+
typeof reducerObj.object[sknative] == "string") {
|
|
232
|
+
return this.derive(this.refs.binding.SkipRuntime_Collection__nativeMapReduce(this.collection, skmapper, reducerObj.object[sknative]));
|
|
151
233
|
}
|
|
152
234
|
else {
|
|
153
|
-
const skreducer = this.refs.binding.SkipRuntime_createReducer(this.refs.handles.register(reducerObj)
|
|
235
|
+
const skreducer = this.refs.binding.SkipRuntime_createReducer(this.refs.handles.register(reducerObj));
|
|
154
236
|
return this.derive(this.refs.binding.SkipRuntime_Collection__mapReduce(this.collection, skmapper, skreducer));
|
|
155
237
|
}
|
|
156
238
|
};
|
|
157
239
|
}
|
|
158
240
|
reduce(reducer, ...params) {
|
|
159
241
|
const reducerObj = instantiateUserObject("Reducer", reducer, params);
|
|
160
|
-
if (sknative in reducerObj &&
|
|
161
|
-
|
|
242
|
+
if (sknative in reducerObj.object &&
|
|
243
|
+
typeof reducerObj.object[sknative] == "string") {
|
|
244
|
+
return this.derive(this.refs.binding.SkipRuntime_Collection__nativeReduce(this.collection, reducerObj.object[sknative]));
|
|
162
245
|
}
|
|
163
246
|
else {
|
|
164
|
-
const skreducer = this.refs.binding.SkipRuntime_createReducer(this.refs.handles.register(reducerObj)
|
|
247
|
+
const skreducer = this.refs.binding.SkipRuntime_createReducer(this.refs.handles.register(reducerObj));
|
|
165
248
|
return this.derive(this.refs.binding.SkipRuntime_Collection__reduce(this.collection, skreducer));
|
|
166
249
|
}
|
|
167
250
|
}
|
|
168
251
|
merge(...others) {
|
|
169
252
|
const otherNames = others.map((other) => EagerCollectionImpl.getName(other));
|
|
170
|
-
const mapped = this.refs.binding.SkipRuntime_Collection__merge(this.collection, this.refs.
|
|
253
|
+
const mapped = this.refs.binding.SkipRuntime_Collection__merge(this.collection, this.refs.json().exportJSON(otherNames));
|
|
171
254
|
return this.derive(mapped);
|
|
172
255
|
}
|
|
173
256
|
derive(collection) {
|
|
@@ -178,59 +261,61 @@ class EagerCollectionImpl extends SkManaged {
|
|
|
178
261
|
}
|
|
179
262
|
}
|
|
180
263
|
class CollectionWriter {
|
|
181
|
-
constructor(collection, refs) {
|
|
264
|
+
constructor(collection, refs, forkName) {
|
|
182
265
|
this.collection = collection;
|
|
183
266
|
this.refs = refs;
|
|
267
|
+
this.forkName = forkName;
|
|
184
268
|
}
|
|
185
269
|
async update(values, isInit) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
});
|
|
197
|
-
if (errorHdl)
|
|
198
|
-
reject(this.refs.handles.deleteHandle(errorHdl));
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
error(error) {
|
|
202
|
-
if (!this.refs.needGC()) {
|
|
203
|
-
throw new SkipError("CollectionWriter.update cannot be performed.");
|
|
270
|
+
this.refs.setFork(this.getForkName());
|
|
271
|
+
const uuid = crypto.randomUUID();
|
|
272
|
+
const fork = this.fork(uuid);
|
|
273
|
+
try {
|
|
274
|
+
await fork.update_(values, isInit);
|
|
275
|
+
fork.merge();
|
|
276
|
+
}
|
|
277
|
+
catch (ex) {
|
|
278
|
+
fork.abortFork();
|
|
279
|
+
throw ex;
|
|
204
280
|
}
|
|
205
|
-
const errorHdl = this.refs.runWithGC(() => this.refs.binding.SkipRuntime_CollectionWriter__error(this.collection, this.refs.skjson.exportJSON(this.toJSONError(error))));
|
|
206
|
-
if (errorHdl)
|
|
207
|
-
throw this.refs.handles.deleteHandle(errorHdl);
|
|
208
281
|
}
|
|
209
|
-
|
|
282
|
+
update_(values, isInit) {
|
|
283
|
+
this.refs.setFork(this.forkName);
|
|
210
284
|
if (!this.refs.needGC()) {
|
|
211
285
|
throw new SkipError("CollectionWriter.update cannot be performed.");
|
|
212
286
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
287
|
+
return this.refs.runAsync(() => this.refs.binding.SkipRuntime_CollectionWriter__update(this.collection, this.refs.json().exportJSON(values), isInit));
|
|
288
|
+
}
|
|
289
|
+
fork(name) {
|
|
290
|
+
this.refs.setFork(this.forkName);
|
|
291
|
+
this.refs.fork(name);
|
|
292
|
+
return new CollectionWriter(this.collection, this.refs, name);
|
|
293
|
+
}
|
|
294
|
+
merge() {
|
|
295
|
+
if (!this.forkName)
|
|
296
|
+
throw new Error("Unable to merge fork on main.");
|
|
297
|
+
this.refs.setFork(this.forkName);
|
|
298
|
+
this.refs.merge();
|
|
299
|
+
}
|
|
300
|
+
abortFork() {
|
|
301
|
+
if (!this.forkName)
|
|
302
|
+
throw new Error("Unable to abord fork on main.");
|
|
303
|
+
this.refs.setFork(this.forkName);
|
|
304
|
+
this.refs.abortFork();
|
|
305
|
+
}
|
|
306
|
+
getForkName() {
|
|
307
|
+
const forkName = this.forkName;
|
|
308
|
+
if (!forkName)
|
|
309
|
+
return null;
|
|
310
|
+
if (!this.refs.runWithGC(() => this.refs.binding.SkipRuntime_Runtime__forkExists(forkName))) {
|
|
311
|
+
this.forkName = null;
|
|
312
|
+
}
|
|
313
|
+
return this.forkName;
|
|
227
314
|
}
|
|
228
315
|
}
|
|
229
|
-
class ContextImpl
|
|
316
|
+
class ContextImpl {
|
|
230
317
|
constructor(refs) {
|
|
231
|
-
super();
|
|
232
318
|
this.refs = refs;
|
|
233
|
-
Object.freeze(this);
|
|
234
319
|
}
|
|
235
320
|
createLazyCollection(compute, ...params) {
|
|
236
321
|
const computeObj = instantiateUserObject("LazyCompute", compute, params);
|
|
@@ -239,11 +324,12 @@ class ContextImpl extends SkManaged {
|
|
|
239
324
|
return new LazyCollectionImpl(lazyCollection, this.refs);
|
|
240
325
|
}
|
|
241
326
|
useExternalResource(resource) {
|
|
242
|
-
const collection = this.refs.binding.SkipRuntime_Context__useExternalResource(resource.service, resource.identifier, this.refs.
|
|
327
|
+
const collection = this.refs.binding.SkipRuntime_Context__useExternalResource(resource.service, resource.identifier, this.refs.json().exportJSON(resource.params ?? {}));
|
|
243
328
|
return new EagerCollectionImpl(collection, this.refs);
|
|
244
329
|
}
|
|
245
330
|
jsonExtract(value, pattern) {
|
|
246
|
-
|
|
331
|
+
const skjson = this.refs.json();
|
|
332
|
+
return skjson.importJSON(this.refs.binding.SkipRuntime_Context__jsonExtract(skjson.exportJSON(value), pattern));
|
|
247
333
|
}
|
|
248
334
|
}
|
|
249
335
|
export class ServiceInstanceFactory {
|
|
@@ -259,27 +345,21 @@ export class ServiceInstanceFactory {
|
|
|
259
345
|
* and operations to manage subscriptions and the service itself.
|
|
260
346
|
*/
|
|
261
347
|
export class ServiceInstance {
|
|
262
|
-
constructor(refs) {
|
|
348
|
+
constructor(refs, forkName, definition) {
|
|
263
349
|
this.refs = refs;
|
|
350
|
+
this.forkName = forkName;
|
|
351
|
+
this.definition = definition;
|
|
264
352
|
}
|
|
265
353
|
/**
|
|
266
354
|
* Instantiate a resource with some parameters and client session authentication token
|
|
267
355
|
* @param identifier - The resource instance identifier
|
|
268
356
|
* @param resource - A resource name, which must correspond to a key in this `SkipService`'s `resources` field
|
|
269
357
|
* @param params - Resource parameters, which will be passed to the resource constructor specified in this `SkipService`'s `resources` field
|
|
358
|
+
* @returns The resulting promise
|
|
270
359
|
*/
|
|
271
360
|
instantiateResource(identifier, resource, params) {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
const exHdl = this.refs.handles.register({
|
|
275
|
-
resolve,
|
|
276
|
-
reject: (ex) => reject(ex),
|
|
277
|
-
});
|
|
278
|
-
return this.refs.binding.SkipRuntime_Runtime__createResource(identifier, resource, this.refs.skjson.exportJSON(params), this.refs.binding.SkipRuntime_createExecutor(exHdl));
|
|
279
|
-
});
|
|
280
|
-
if (errorHdl)
|
|
281
|
-
reject(this.refs.handles.deleteHandle(errorHdl));
|
|
282
|
-
});
|
|
361
|
+
this.refs.setFork(this.forkName);
|
|
362
|
+
return this.refs.runAsync(() => this.refs.binding.SkipRuntime_Runtime__createResource(identifier, resource, this.refs.json().exportJSON(params)));
|
|
283
363
|
}
|
|
284
364
|
/**
|
|
285
365
|
* Creates if not exists and get all current values of specified resource
|
|
@@ -291,15 +371,15 @@ export class ServiceInstance {
|
|
|
291
371
|
const uuid = crypto.randomUUID();
|
|
292
372
|
await this.instantiateResource(uuid, resource, params);
|
|
293
373
|
try {
|
|
374
|
+
this.refs.setFork(this.forkName);
|
|
294
375
|
const result = this.refs.runWithGC(() => {
|
|
295
|
-
return this.refs
|
|
376
|
+
return this.refs
|
|
377
|
+
.json()
|
|
378
|
+
.importJSON(this.refs.binding.SkipRuntime_Runtime__getAll(resource, this.refs.json().exportJSON(params)), true);
|
|
296
379
|
});
|
|
297
380
|
if (typeof result == "number")
|
|
298
381
|
throw this.refs.handles.deleteHandle(result);
|
|
299
|
-
|
|
300
|
-
if (info.errors.length > 0)
|
|
301
|
-
throw new SkipError(JSON.stringify(info.errors));
|
|
302
|
-
return info.payload;
|
|
382
|
+
return result;
|
|
303
383
|
}
|
|
304
384
|
finally {
|
|
305
385
|
this.closeResourceInstance(uuid);
|
|
@@ -316,15 +396,14 @@ export class ServiceInstance {
|
|
|
316
396
|
const uuid = crypto.randomUUID();
|
|
317
397
|
await this.instantiateResource(uuid, resource, params);
|
|
318
398
|
try {
|
|
399
|
+
this.refs.setFork(this.forkName);
|
|
400
|
+
const skjson = this.refs.json();
|
|
319
401
|
const result = this.refs.runWithGC(() => {
|
|
320
|
-
return
|
|
402
|
+
return skjson.importJSON(this.refs.binding.SkipRuntime_Runtime__getForKey(resource, skjson.exportJSON(params), skjson.exportJSON(key)), true);
|
|
321
403
|
});
|
|
322
404
|
if (typeof result == "number")
|
|
323
405
|
throw this.refs.handles.deleteHandle(result);
|
|
324
|
-
|
|
325
|
-
if (info.errors.length > 0)
|
|
326
|
-
throw new SkipError(JSON.stringify(info.errors));
|
|
327
|
-
return info.payload;
|
|
406
|
+
return result;
|
|
328
407
|
}
|
|
329
408
|
finally {
|
|
330
409
|
this.closeResourceInstance(uuid);
|
|
@@ -335,6 +414,7 @@ export class ServiceInstance {
|
|
|
335
414
|
* @param resourceInstanceId - The resource identifier
|
|
336
415
|
*/
|
|
337
416
|
closeResourceInstance(resourceInstanceId) {
|
|
417
|
+
this.refs.setFork(this.forkName);
|
|
338
418
|
const errorHdl = this.refs.runWithGC(() => {
|
|
339
419
|
return this.refs.binding.SkipRuntime_Runtime__closeResource(resourceInstanceId);
|
|
340
420
|
});
|
|
@@ -352,6 +432,7 @@ export class ServiceInstance {
|
|
|
352
432
|
* @returns A subscription identifier
|
|
353
433
|
*/
|
|
354
434
|
subscribe(resourceInstanceId, notifier, watermark) {
|
|
435
|
+
this.refs.setFork(this.forkName);
|
|
355
436
|
const session = this.refs.runWithGC(() => {
|
|
356
437
|
const sknotifier = this.refs.binding.SkipRuntime_createNotifier(this.refs.handles.register(notifier));
|
|
357
438
|
return this.refs.binding.SkipRuntime_Runtime__subscribe(resourceInstanceId, sknotifier, watermark ?? null);
|
|
@@ -365,13 +446,14 @@ export class ServiceInstance {
|
|
|
365
446
|
else if (session < 0n) {
|
|
366
447
|
throw this.refs.handles.deleteHandle(Number(-session));
|
|
367
448
|
}
|
|
368
|
-
return
|
|
449
|
+
return resourceInstanceId;
|
|
369
450
|
}
|
|
370
451
|
/**
|
|
371
452
|
* Terminate a client's subscription to a reactive resource instance
|
|
372
453
|
* @param id - The subscription identifier returned by a call to `subscribe`
|
|
373
454
|
*/
|
|
374
455
|
unsubscribe(id) {
|
|
456
|
+
this.refs.setFork(this.forkName);
|
|
375
457
|
const errorHdl = this.refs.runWithGC(() => {
|
|
376
458
|
return this.refs.binding.SkipRuntime_Runtime__unsubscribe(id);
|
|
377
459
|
});
|
|
@@ -384,18 +466,34 @@ export class ServiceInstance {
|
|
|
384
466
|
* @param collection - the name of the input collection to update
|
|
385
467
|
* @param entries - entries to update in the collection.
|
|
386
468
|
*/
|
|
387
|
-
update(collection, entries) {
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
469
|
+
async update(collection, entries) {
|
|
470
|
+
this.refs.setFork(this.forkName);
|
|
471
|
+
const uuid = crypto.randomUUID();
|
|
472
|
+
const fork = this.fork(uuid);
|
|
473
|
+
try {
|
|
474
|
+
await fork.update_(collection, entries);
|
|
475
|
+
fork.merge([]);
|
|
476
|
+
}
|
|
477
|
+
catch (ex) {
|
|
478
|
+
fork.abortFork();
|
|
479
|
+
throw ex;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
async update_(collection, entries) {
|
|
483
|
+
this.refs.setFork(this.forkName);
|
|
484
|
+
const result = this.refs.runWithGC(() => {
|
|
485
|
+
const json = this.refs.json();
|
|
486
|
+
return json.importJSON(this.refs.binding.SkipRuntime_Runtime__update(collection, this.refs.json().exportJSON(entries)), true);
|
|
398
487
|
});
|
|
488
|
+
if (Array.isArray(result)) {
|
|
489
|
+
const handles = result;
|
|
490
|
+
const promises = handles.map((h) => this.refs.handles.deleteHandle(h));
|
|
491
|
+
await Promise.all(promises);
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
const errorHdl = result;
|
|
495
|
+
throw this.refs.handles.deleteHandle(errorHdl);
|
|
496
|
+
}
|
|
399
497
|
}
|
|
400
498
|
/**
|
|
401
499
|
* Close all resources and shut down the service.
|
|
@@ -403,19 +501,94 @@ export class ServiceInstance {
|
|
|
403
501
|
* @returns The promise of externals services shutdowns
|
|
404
502
|
*/
|
|
405
503
|
close() {
|
|
504
|
+
this.refs.setFork(this.forkName);
|
|
406
505
|
const result = this.refs.runWithGC(() => {
|
|
407
|
-
return this.refs.
|
|
506
|
+
return this.refs.binding.SkipRuntime_closeService();
|
|
507
|
+
});
|
|
508
|
+
if (result >= 0) {
|
|
509
|
+
return this.refs.handles.deleteHandle(result);
|
|
510
|
+
}
|
|
511
|
+
else {
|
|
512
|
+
const errorHdl = -result;
|
|
513
|
+
return Promise.reject(this.refs.handles.deleteHandle(errorHdl));
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
async reload(service, changes) {
|
|
517
|
+
if (this.forkName) {
|
|
518
|
+
throw new SkipError("Reload cannot be called in transaction.");
|
|
519
|
+
}
|
|
520
|
+
const definition = this.definition.derive(service);
|
|
521
|
+
this.refs.setFork(this.forkName);
|
|
522
|
+
const uuid = crypto.randomUUID();
|
|
523
|
+
const fork = this.fork(uuid);
|
|
524
|
+
let merged = false;
|
|
525
|
+
try {
|
|
526
|
+
const streamsToClose = await fork._reload(definition, changes);
|
|
527
|
+
fork.merge(streamsToClose);
|
|
528
|
+
merged = true;
|
|
529
|
+
this.closeResourceStreams(streamsToClose);
|
|
530
|
+
this.definition = definition;
|
|
531
|
+
}
|
|
532
|
+
catch (ex) {
|
|
533
|
+
if (!merged)
|
|
534
|
+
fork.abortFork();
|
|
535
|
+
throw ex;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
async _reload(definition, changes) {
|
|
539
|
+
this.refs.setFork(this.forkName);
|
|
540
|
+
const result = this.refs.runWithGC(() => {
|
|
541
|
+
this.refs.changes = this.refs.handles.register(changes);
|
|
542
|
+
const skservicehHdl = this.refs.handles.register(definition);
|
|
543
|
+
const skservice = this.refs.binding.SkipRuntime_createService(skservicehHdl);
|
|
544
|
+
const res = this.refs.binding.SkipRuntime_Runtime__reload(skservice);
|
|
545
|
+
this.refs.handles.deleteHandle(this.refs.changes);
|
|
546
|
+
this.refs.changes = null;
|
|
547
|
+
return this.refs.json().importJSON(res, true);
|
|
408
548
|
});
|
|
409
549
|
if (Array.isArray(result)) {
|
|
410
|
-
const handles = result;
|
|
550
|
+
const [handles, res] = result;
|
|
411
551
|
const promises = handles.map((h) => this.refs.handles.deleteHandle(h));
|
|
412
|
-
|
|
552
|
+
await Promise.all(promises);
|
|
553
|
+
return res;
|
|
413
554
|
}
|
|
414
555
|
else {
|
|
415
556
|
const errorHdl = result;
|
|
416
|
-
|
|
557
|
+
throw this.refs.handles.deleteHandle(errorHdl);
|
|
417
558
|
}
|
|
418
559
|
}
|
|
560
|
+
/**
|
|
561
|
+
* Fork the service with current specified name.
|
|
562
|
+
* @param name - the name of the fork.
|
|
563
|
+
* @returns The forked ServiceInstance
|
|
564
|
+
*/
|
|
565
|
+
fork(name) {
|
|
566
|
+
if (this.forkName)
|
|
567
|
+
throw new Error(`Unable to fork ${this.forkName}.`);
|
|
568
|
+
this.refs.setFork(this.forkName);
|
|
569
|
+
this.refs.fork(name);
|
|
570
|
+
return new ServiceInstance(this.refs, name, this.definition);
|
|
571
|
+
}
|
|
572
|
+
merge(ignore) {
|
|
573
|
+
if (!this.forkName)
|
|
574
|
+
throw new Error("Unable to merge fork on main.");
|
|
575
|
+
this.refs.setFork(this.forkName);
|
|
576
|
+
this.refs.merge(ignore);
|
|
577
|
+
}
|
|
578
|
+
abortFork() {
|
|
579
|
+
if (!this.forkName)
|
|
580
|
+
throw new Error("Unable to abord fork on main.");
|
|
581
|
+
this.refs.setFork(this.forkName);
|
|
582
|
+
this.refs.abortFork();
|
|
583
|
+
}
|
|
584
|
+
closeResourceStreams(streams) {
|
|
585
|
+
this.refs.setFork(this.forkName);
|
|
586
|
+
const errorHdl = this.refs.runWithGC(() => {
|
|
587
|
+
return this.refs.binding.SkipRuntime_Runtime__closeResourceStreams(this.refs.json().exportJSON(streams));
|
|
588
|
+
});
|
|
589
|
+
if (errorHdl)
|
|
590
|
+
throw this.refs.handles.deleteHandle(errorHdl);
|
|
591
|
+
}
|
|
419
592
|
}
|
|
420
593
|
class ValuesImpl {
|
|
421
594
|
constructor(skjson, binding, pointer) {
|
|
@@ -486,6 +659,8 @@ export class ToBinding {
|
|
|
486
659
|
this.getError = getError;
|
|
487
660
|
this.stack = new Stack();
|
|
488
661
|
this.handles = new Handles();
|
|
662
|
+
this.forkName = null;
|
|
663
|
+
this.changes = null;
|
|
489
664
|
}
|
|
490
665
|
register(v) {
|
|
491
666
|
return this.handles.register(v);
|
|
@@ -505,14 +680,33 @@ export class ToBinding {
|
|
|
505
680
|
SkipRuntime_getContext() {
|
|
506
681
|
return this.stack.get();
|
|
507
682
|
}
|
|
683
|
+
SkipRuntime_getFork() {
|
|
684
|
+
return this.forkName;
|
|
685
|
+
}
|
|
686
|
+
SkipRuntime_getChangeManager() {
|
|
687
|
+
return this.changes ?? 0;
|
|
688
|
+
}
|
|
689
|
+
setFork(name) {
|
|
690
|
+
this.forkName = name;
|
|
691
|
+
}
|
|
508
692
|
// Mapper
|
|
509
693
|
SkipRuntime_Mapper__mapEntry(skmapper, key, values) {
|
|
510
694
|
const skjson = this.getJsonConverter();
|
|
511
695
|
const mapper = this.handles.get(skmapper);
|
|
512
|
-
const context = new ContextImpl(this
|
|
513
|
-
const result = mapper.mapEntry(skjson.importJSON(key), new ValuesImpl(skjson, this.binding, values), context);
|
|
696
|
+
const context = new ContextImpl(this);
|
|
697
|
+
const result = mapper.object.mapEntry(skjson.importJSON(key), new ValuesImpl(skjson, this.binding, values), context);
|
|
514
698
|
return skjson.exportJSON(Array.from(result));
|
|
515
699
|
}
|
|
700
|
+
SkipRuntime_Mapper__getInfo(skmapper) {
|
|
701
|
+
return this.getInfo(skmapper);
|
|
702
|
+
}
|
|
703
|
+
SkipRuntime_Mapper__isEquals(mapper, other) {
|
|
704
|
+
const object = this.handles.get(mapper);
|
|
705
|
+
if (this.getChanges()?.needMapperReload(object.name)) {
|
|
706
|
+
return 0;
|
|
707
|
+
}
|
|
708
|
+
return this.isEquals(mapper, other);
|
|
709
|
+
}
|
|
516
710
|
SkipRuntime_deleteMapper(mapper) {
|
|
517
711
|
this.handles.deleteHandle(mapper);
|
|
518
712
|
}
|
|
@@ -520,9 +714,20 @@ export class ToBinding {
|
|
|
520
714
|
SkipRuntime_LazyCompute__compute(sklazyCompute, self, skkey) {
|
|
521
715
|
const skjson = this.getJsonConverter();
|
|
522
716
|
const lazyCompute = this.handles.get(sklazyCompute);
|
|
523
|
-
const
|
|
717
|
+
const context = new ContextImpl(this);
|
|
718
|
+
const result = lazyCompute.object.compute(new LazyCollectionImpl(self, this), skjson.importJSON(skkey), context);
|
|
524
719
|
return skjson.exportJSON(Array.from(result));
|
|
525
720
|
}
|
|
721
|
+
SkipRuntime_LazyCompute__getInfo(lazyCompute) {
|
|
722
|
+
return this.getInfo(lazyCompute);
|
|
723
|
+
}
|
|
724
|
+
SkipRuntime_LazyCompute__isEquals(lazyCompute, other) {
|
|
725
|
+
const object = this.handles.get(lazyCompute);
|
|
726
|
+
if (this.getChanges()?.needLazyComputeReload(object.name)) {
|
|
727
|
+
return 0;
|
|
728
|
+
}
|
|
729
|
+
return this.isEquals(lazyCompute, other);
|
|
730
|
+
}
|
|
526
731
|
SkipRuntime_deleteLazyCompute(lazyCompute) {
|
|
527
732
|
this.handles.deleteHandle(lazyCompute);
|
|
528
733
|
}
|
|
@@ -532,46 +737,83 @@ export class ToBinding {
|
|
|
532
737
|
const resource = this.handles.get(skresource);
|
|
533
738
|
const collections = {};
|
|
534
739
|
const keysIds = skjson.importJSON(skcollections);
|
|
535
|
-
const refs = this.refs();
|
|
536
740
|
for (const [key, name] of Object.entries(keysIds)) {
|
|
537
|
-
collections[key] = new EagerCollectionImpl(name,
|
|
741
|
+
collections[key] = new EagerCollectionImpl(name, this);
|
|
538
742
|
}
|
|
539
|
-
const collection = resource.instantiate(collections, new ContextImpl(
|
|
743
|
+
const collection = resource.instantiate(collections, new ContextImpl(this));
|
|
540
744
|
return EagerCollectionImpl.getName(collection);
|
|
541
745
|
}
|
|
542
746
|
SkipRuntime_deleteResource(resource) {
|
|
543
747
|
this.handles.deleteHandle(resource);
|
|
544
748
|
}
|
|
545
|
-
//
|
|
546
|
-
|
|
547
|
-
const skjson = this.getJsonConverter();
|
|
548
|
-
const builder = this.handles.get(skbuilder);
|
|
549
|
-
const resource = builder.build(skjson.importJSON(skparams));
|
|
550
|
-
return this.binding.SkipRuntime_createResource(this.handles.register(resource));
|
|
551
|
-
}
|
|
552
|
-
SkipRuntime_deleteResourceBuilder(builder) {
|
|
553
|
-
this.handles.deleteHandle(builder);
|
|
554
|
-
}
|
|
555
|
-
// Service
|
|
556
|
-
SkipRuntime_Service__createGraph(skservice, skcollections) {
|
|
749
|
+
// ServiceDefinition
|
|
750
|
+
SkipRuntime_ServiceDefinition__createGraph(skservice, skcollections) {
|
|
557
751
|
const skjson = this.getJsonConverter();
|
|
558
752
|
const service = this.handles.get(skservice);
|
|
559
753
|
const collections = {};
|
|
560
754
|
const keysIds = skjson.importJSON(skcollections);
|
|
561
|
-
const refs = this.refs();
|
|
562
755
|
for (const [key, name] of Object.entries(keysIds)) {
|
|
563
|
-
collections[key] = new EagerCollectionImpl(name,
|
|
756
|
+
collections[key] = new EagerCollectionImpl(name, this);
|
|
564
757
|
}
|
|
565
|
-
const result = service.createGraph(collections, new ContextImpl(
|
|
758
|
+
const result = service.createGraph(collections, new ContextImpl(this));
|
|
566
759
|
const collectionsNames = {};
|
|
567
760
|
for (const [name, collection] of Object.entries(result)) {
|
|
568
761
|
collectionsNames[name] = EagerCollectionImpl.getName(collection);
|
|
569
762
|
}
|
|
570
763
|
return skjson.exportJSON(collectionsNames);
|
|
571
764
|
}
|
|
765
|
+
SkipRuntime_ServiceDefinition__inputs(skservice) {
|
|
766
|
+
const skjson = this.getJsonConverter();
|
|
767
|
+
const service = this.handles.get(skservice);
|
|
768
|
+
return skjson.exportJSON(service.inputs());
|
|
769
|
+
}
|
|
770
|
+
SkipRuntime_ServiceDefinition__resources(skservice) {
|
|
771
|
+
const skjson = this.getJsonConverter();
|
|
772
|
+
const service = this.handles.get(skservice);
|
|
773
|
+
return skjson.exportJSON(service.resources());
|
|
774
|
+
}
|
|
775
|
+
SkipRuntime_ServiceDefinition__initialData(skservice, name) {
|
|
776
|
+
const skjson = this.getJsonConverter();
|
|
777
|
+
const service = this.handles.get(skservice);
|
|
778
|
+
return skjson.exportJSON(service.initialData(name));
|
|
779
|
+
}
|
|
780
|
+
SkipRuntime_ServiceDefinition__buildResource(skservice, name, skparams) {
|
|
781
|
+
const skjson = this.getJsonConverter();
|
|
782
|
+
const service = this.handles.get(skservice);
|
|
783
|
+
const resource = service.buildResource(name, skjson.importJSON(skparams));
|
|
784
|
+
return this.binding.SkipRuntime_createResource(this.handles.register(resource));
|
|
785
|
+
}
|
|
786
|
+
SkipRuntime_ServiceDefinition__subscribe(skservice, external, writerId, instance, resource, skparams) {
|
|
787
|
+
const skjson = this.getJsonConverter();
|
|
788
|
+
const service = this.handles.get(skservice);
|
|
789
|
+
const writer = new CollectionWriter(writerId, this, this.forkName);
|
|
790
|
+
const params = skjson.importJSON(skparams, true);
|
|
791
|
+
return this.handles.register(service.subscribe(external, writer, instance, resource, params));
|
|
792
|
+
}
|
|
793
|
+
SkipRuntime_ServiceDefinition__unsubscribe(skservice, external, instance) {
|
|
794
|
+
const service = this.handles.get(skservice);
|
|
795
|
+
service.unsubscribe(external, instance);
|
|
796
|
+
}
|
|
797
|
+
SkipRuntime_ServiceDefinition__shutdown(skservice) {
|
|
798
|
+
const service = this.handles.get(skservice);
|
|
799
|
+
return this.handles.register(service.shutdown());
|
|
800
|
+
}
|
|
572
801
|
SkipRuntime_deleteService(service) {
|
|
573
802
|
this.handles.deleteHandle(service);
|
|
574
803
|
}
|
|
804
|
+
// Change manager
|
|
805
|
+
SkipRuntime_ChangeManager__needInputReload(skmanager, name) {
|
|
806
|
+
const manager = this.handles.get(skmanager);
|
|
807
|
+
return manager.needInputReload(name) ? 1 : 0;
|
|
808
|
+
}
|
|
809
|
+
SkipRuntime_ChangeManager__needResourceReload(skmanager, name) {
|
|
810
|
+
const manager = this.handles.get(skmanager);
|
|
811
|
+
return manager.needResourceReload(name);
|
|
812
|
+
}
|
|
813
|
+
SkipRuntime_ChangeManager__needExternalServiceReload(skmanager, name, resource) {
|
|
814
|
+
const manager = this.handles.get(skmanager);
|
|
815
|
+
return manager.needExternalServiceReload(name, resource) ? 1 : 0;
|
|
816
|
+
}
|
|
575
817
|
// Notifier
|
|
576
818
|
SkipRuntime_Notifier__subscribed(sknotifier) {
|
|
577
819
|
const notifier = this.handles.get(sknotifier);
|
|
@@ -596,88 +838,57 @@ export class ToBinding {
|
|
|
596
838
|
this.handles.deleteHandle(notifier);
|
|
597
839
|
}
|
|
598
840
|
// Reducer
|
|
599
|
-
|
|
841
|
+
SkipRuntime_Reducer__init(skreducer) {
|
|
600
842
|
const skjson = this.getJsonConverter();
|
|
601
843
|
const reducer = this.handles.get(skreducer);
|
|
602
|
-
return skjson.exportJSON(reducer.
|
|
844
|
+
return skjson.exportJSON(reducer.object.initial);
|
|
603
845
|
}
|
|
604
|
-
|
|
846
|
+
SkipRuntime_Reducer__add(skreducer, skacc, skvalue) {
|
|
605
847
|
const skjson = this.getJsonConverter();
|
|
606
848
|
const reducer = this.handles.get(skreducer);
|
|
607
|
-
return skjson.exportJSON(reducer.
|
|
849
|
+
return skjson.exportJSON(reducer.object.add(skacc ? skjson.importJSON(skacc) : null, skjson.importJSON(skvalue)));
|
|
608
850
|
}
|
|
609
|
-
|
|
610
|
-
this.handles.deleteHandle(reducer);
|
|
611
|
-
}
|
|
612
|
-
// ExternalService
|
|
613
|
-
SkipRuntime_ExternalService__subscribe(sksupplier, writerId, instance, resource, skparams) {
|
|
851
|
+
SkipRuntime_Reducer__remove(skreducer, skacc, skvalue) {
|
|
614
852
|
const skjson = this.getJsonConverter();
|
|
615
|
-
const
|
|
616
|
-
|
|
617
|
-
const params = skjson.importJSON(skparams, true);
|
|
618
|
-
// Ensure notification is made outside the current context update
|
|
619
|
-
setTimeout(() => {
|
|
620
|
-
supplier
|
|
621
|
-
.subscribe(instance, resource, params, {
|
|
622
|
-
update: writer.update.bind(writer),
|
|
623
|
-
error: writer.error.bind(writer),
|
|
624
|
-
})
|
|
625
|
-
.then(() => writer.initialized())
|
|
626
|
-
.catch((e) => writer.initialized(e instanceof Error
|
|
627
|
-
? e.message
|
|
628
|
-
: JSON.stringify(e, Object.getOwnPropertyNames(e))));
|
|
629
|
-
}, 0);
|
|
630
|
-
}
|
|
631
|
-
SkipRuntime_ExternalService__unsubscribe(sksupplier, instance) {
|
|
632
|
-
const supplier = this.handles.get(sksupplier);
|
|
633
|
-
supplier.unsubscribe(instance);
|
|
634
|
-
}
|
|
635
|
-
SkipRuntime_ExternalService__shutdown(sksupplier) {
|
|
636
|
-
const supplier = this.handles.get(sksupplier);
|
|
637
|
-
return this.handles.register(supplier.shutdown());
|
|
853
|
+
const reducer = this.handles.get(skreducer);
|
|
854
|
+
return skjson.exportJSON(reducer.object.remove(skjson.importJSON(skacc), skjson.importJSON(skvalue)));
|
|
638
855
|
}
|
|
639
|
-
|
|
640
|
-
this.handles.
|
|
856
|
+
SkipRuntime_Reducer__isEquals(reducer, other) {
|
|
857
|
+
const object = this.handles.get(reducer);
|
|
858
|
+
if (this.getChanges()?.needReducerReload(object.name)) {
|
|
859
|
+
return 0;
|
|
860
|
+
}
|
|
861
|
+
return this.isEquals(reducer, other);
|
|
641
862
|
}
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
const checker = this.handles.get(skexecutor);
|
|
645
|
-
checker.resolve();
|
|
863
|
+
SkipRuntime_Reducer__getInfo(reducer) {
|
|
864
|
+
return this.getInfo(reducer);
|
|
646
865
|
}
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
checker.reject(this.handles.deleteHandle(error));
|
|
866
|
+
SkipRuntime_deleteReducer(reducer) {
|
|
867
|
+
this.handles.deleteHandle(reducer);
|
|
650
868
|
}
|
|
651
|
-
|
|
652
|
-
this.
|
|
869
|
+
async initService(service) {
|
|
870
|
+
this.setFork(null);
|
|
871
|
+
const uuid = crypto.randomUUID();
|
|
872
|
+
this.fork(uuid);
|
|
873
|
+
try {
|
|
874
|
+
this.setFork(uuid);
|
|
875
|
+
const definition = new ServiceDefinition(service);
|
|
876
|
+
await this.initService_(definition);
|
|
877
|
+
this.setFork(uuid);
|
|
878
|
+
this.merge();
|
|
879
|
+
return new ServiceInstance(this, null, definition);
|
|
880
|
+
}
|
|
881
|
+
catch (ex) {
|
|
882
|
+
this.setFork(uuid);
|
|
883
|
+
this.abortFork();
|
|
884
|
+
throw ex;
|
|
885
|
+
}
|
|
653
886
|
}
|
|
654
|
-
|
|
655
|
-
return
|
|
656
|
-
const
|
|
657
|
-
const
|
|
658
|
-
|
|
659
|
-
if (service.externalServices) {
|
|
660
|
-
for (const [name, remote] of Object.entries(service.externalServices)) {
|
|
661
|
-
const skremote = refs.binding.SkipRuntime_createExternalService(refs.handles.register(remote));
|
|
662
|
-
refs.binding.SkipRuntime_ExternalServiceMap__add(skExternalServices, name, skremote);
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
const skresources = refs.binding.SkipRuntime_ResourceBuilderMap__create();
|
|
666
|
-
for (const [name, builder] of Object.entries(service.resources)) {
|
|
667
|
-
const skbuilder = refs.binding.SkipRuntime_createResourceBuilder(refs.handles.register(new ResourceBuilder(builder)));
|
|
668
|
-
refs.binding.SkipRuntime_ResourceBuilderMap__add(skresources, name, skbuilder);
|
|
669
|
-
}
|
|
670
|
-
const skservice = refs.binding.SkipRuntime_createService(refs.handles.register(service), refs.skjson.exportJSON(service.initialData ?? {}), skresources, skExternalServices);
|
|
671
|
-
const exHdl = refs.handles.register({
|
|
672
|
-
resolve: () => {
|
|
673
|
-
resolve(new ServiceInstance(refs));
|
|
674
|
-
},
|
|
675
|
-
reject: (ex) => reject(ex),
|
|
676
|
-
});
|
|
677
|
-
return refs.binding.SkipRuntime_initService(skservice, refs.binding.SkipRuntime_createExecutor(exHdl));
|
|
678
|
-
});
|
|
679
|
-
if (errorHdl)
|
|
680
|
-
reject(refs.handles.deleteHandle(errorHdl));
|
|
887
|
+
initService_(definition) {
|
|
888
|
+
return this.runAsync(() => {
|
|
889
|
+
const skservicehHdl = this.handles.register(definition);
|
|
890
|
+
const skservice = this.binding.SkipRuntime_createService(skservicehHdl);
|
|
891
|
+
return this.binding.SkipRuntime_initService(skservice);
|
|
681
892
|
});
|
|
682
893
|
}
|
|
683
894
|
//
|
|
@@ -690,8 +901,132 @@ export class ToBinding {
|
|
|
690
901
|
needGC() {
|
|
691
902
|
return this.SkipRuntime_getContext() == null;
|
|
692
903
|
}
|
|
693
|
-
|
|
694
|
-
return
|
|
904
|
+
json() {
|
|
905
|
+
return this.getJsonConverter();
|
|
906
|
+
}
|
|
907
|
+
fork(name) {
|
|
908
|
+
const errorHdl = this.runWithGC(() => this.binding.SkipRuntime_Runtime__fork(name));
|
|
909
|
+
if (errorHdl)
|
|
910
|
+
throw this.handles.deleteHandle(errorHdl);
|
|
911
|
+
}
|
|
912
|
+
merge(ignore = []) {
|
|
913
|
+
const errorHdl = this.runWithGC(() => this.binding.SkipRuntime_Runtime__merge(this.json().exportJSON(ignore)));
|
|
914
|
+
if (errorHdl)
|
|
915
|
+
throw this.handles.deleteHandle(errorHdl);
|
|
916
|
+
}
|
|
917
|
+
abortFork() {
|
|
918
|
+
const errorHdl = this.runWithGC(() => this.binding.SkipRuntime_Runtime__abortFork());
|
|
919
|
+
if (errorHdl)
|
|
920
|
+
throw this.handles.deleteHandle(errorHdl);
|
|
921
|
+
}
|
|
922
|
+
async runAsync(fn) {
|
|
923
|
+
const result = this.runWithGC(() => {
|
|
924
|
+
return this.json().importJSON(fn(), true);
|
|
925
|
+
});
|
|
926
|
+
if (Array.isArray(result)) {
|
|
927
|
+
const handles = result;
|
|
928
|
+
const promises = handles.map((h) => this.handles.deleteHandle(h));
|
|
929
|
+
await Promise.all(promises);
|
|
930
|
+
}
|
|
931
|
+
else {
|
|
932
|
+
const errorHdl = result;
|
|
933
|
+
throw this.handles.deleteHandle(errorHdl);
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
deepEquals(a, b) {
|
|
937
|
+
// Same reference or both NaN
|
|
938
|
+
if (a === b)
|
|
939
|
+
return true;
|
|
940
|
+
if (a !== a && b !== b)
|
|
941
|
+
return true; // NaN check
|
|
942
|
+
// Different types or one is null
|
|
943
|
+
if (typeof a !== typeof b || a === null || b === null)
|
|
944
|
+
return false;
|
|
945
|
+
// Primitives already checked by ===
|
|
946
|
+
if (typeof a !== "object" || typeof b !== "object")
|
|
947
|
+
return false;
|
|
948
|
+
// Arrays
|
|
949
|
+
if (Array.isArray(a)) {
|
|
950
|
+
if (!Array.isArray(b) || a.length !== b.length)
|
|
951
|
+
return false;
|
|
952
|
+
for (let i = 0; i < a.length; i++) {
|
|
953
|
+
if (!this.deepEquals(a[i], b[i]))
|
|
954
|
+
return false;
|
|
955
|
+
}
|
|
956
|
+
return true;
|
|
957
|
+
}
|
|
958
|
+
// Different array status
|
|
959
|
+
if (Array.isArray(b))
|
|
960
|
+
return false;
|
|
961
|
+
// Objects
|
|
962
|
+
const keysA = Object.keys(a);
|
|
963
|
+
const keysB = Object.keys(b);
|
|
964
|
+
if (keysA.length !== keysB.length)
|
|
965
|
+
return false;
|
|
966
|
+
for (const key of keysA) {
|
|
967
|
+
if (!Object.prototype.hasOwnProperty.call(b, key) ||
|
|
968
|
+
!this.deepEquals(a[key], b[key]))
|
|
969
|
+
return false;
|
|
970
|
+
}
|
|
971
|
+
return true;
|
|
972
|
+
}
|
|
973
|
+
getInfo(skmapper) {
|
|
974
|
+
const skjson = this.getJsonConverter();
|
|
975
|
+
const object = this.handles.get(skmapper);
|
|
976
|
+
const name = object.name;
|
|
977
|
+
const parameters = object.params.map((v) => {
|
|
978
|
+
if (v instanceof EagerCollectionImpl) {
|
|
979
|
+
return {
|
|
980
|
+
type: "collection",
|
|
981
|
+
value: v.collection,
|
|
982
|
+
};
|
|
983
|
+
}
|
|
984
|
+
if (v instanceof LazyCollectionImpl) {
|
|
985
|
+
return {
|
|
986
|
+
type: "collection",
|
|
987
|
+
value: v.lazyCollection,
|
|
988
|
+
};
|
|
989
|
+
}
|
|
990
|
+
return { type: "data", value: v };
|
|
991
|
+
});
|
|
992
|
+
return skjson.exportJSON({ name, parameters });
|
|
993
|
+
}
|
|
994
|
+
isEquals(mapper, other) {
|
|
995
|
+
const object = this.handles.get(mapper);
|
|
996
|
+
const oobject = this.handles.get(other);
|
|
997
|
+
if (object.object.constructor != oobject.object.constructor) {
|
|
998
|
+
return 0;
|
|
999
|
+
}
|
|
1000
|
+
if (object.params.length != oobject.params.length)
|
|
1001
|
+
return 0;
|
|
1002
|
+
for (const [i, param] of object.params.entries()) {
|
|
1003
|
+
const oparam = oobject.params[i];
|
|
1004
|
+
if (param instanceof EagerCollectionImpl) {
|
|
1005
|
+
if (oparam instanceof EagerCollectionImpl) {
|
|
1006
|
+
if (param.collection != oparam.collection)
|
|
1007
|
+
return 0;
|
|
1008
|
+
}
|
|
1009
|
+
else {
|
|
1010
|
+
return 0;
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
else if (param instanceof LazyCollectionImpl) {
|
|
1014
|
+
if (oparam instanceof LazyCollectionImpl) {
|
|
1015
|
+
if (param.lazyCollection != oparam.lazyCollection)
|
|
1016
|
+
return 0;
|
|
1017
|
+
}
|
|
1018
|
+
else {
|
|
1019
|
+
return 0;
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
else if (!this.deepEquals(param, oparam)) {
|
|
1023
|
+
return 0;
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
return 1;
|
|
1027
|
+
}
|
|
1028
|
+
getChanges() {
|
|
1029
|
+
return this.changes ? this.handles.get(this.changes) : null;
|
|
695
1030
|
}
|
|
696
1031
|
}
|
|
697
1032
|
//# sourceMappingURL=index.js.map
|