@skipruntime/core 0.0.16 → 0.0.17
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 +530 -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 +715 -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.forkName);
|
|
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.getForkName());
|
|
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,95 @@ 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
|
+
console.error(ex);
|
|
534
|
+
if (!merged)
|
|
535
|
+
fork.abortFork();
|
|
536
|
+
throw ex;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
async _reload(definition, changes) {
|
|
540
|
+
this.refs.setFork(this.forkName);
|
|
541
|
+
const result = this.refs.runWithGC(() => {
|
|
542
|
+
this.refs.changes = this.refs.handles.register(changes);
|
|
543
|
+
const skservicehHdl = this.refs.handles.register(definition);
|
|
544
|
+
const skservice = this.refs.binding.SkipRuntime_createService(skservicehHdl);
|
|
545
|
+
const res = this.refs.binding.SkipRuntime_Runtime__reload(skservice);
|
|
546
|
+
this.refs.handles.deleteHandle(this.refs.changes);
|
|
547
|
+
this.refs.changes = null;
|
|
548
|
+
return this.refs.json().importJSON(res, true);
|
|
408
549
|
});
|
|
409
550
|
if (Array.isArray(result)) {
|
|
410
|
-
const handles = result;
|
|
551
|
+
const [handles, res] = result;
|
|
411
552
|
const promises = handles.map((h) => this.refs.handles.deleteHandle(h));
|
|
412
|
-
|
|
553
|
+
await Promise.all(promises);
|
|
554
|
+
return res;
|
|
413
555
|
}
|
|
414
556
|
else {
|
|
415
557
|
const errorHdl = result;
|
|
416
|
-
|
|
558
|
+
throw this.refs.handles.deleteHandle(errorHdl);
|
|
417
559
|
}
|
|
418
560
|
}
|
|
561
|
+
/**
|
|
562
|
+
* Fork the service with current specified name.
|
|
563
|
+
* @param name - the name of the fork.
|
|
564
|
+
* @returns The forked ServiceInstance
|
|
565
|
+
*/
|
|
566
|
+
fork(name) {
|
|
567
|
+
if (this.forkName)
|
|
568
|
+
throw new Error(`Unable to fork ${this.forkName}.`);
|
|
569
|
+
this.refs.setFork(this.forkName);
|
|
570
|
+
this.refs.fork(name);
|
|
571
|
+
return new ServiceInstance(this.refs, name, this.definition);
|
|
572
|
+
}
|
|
573
|
+
merge(ignore) {
|
|
574
|
+
if (!this.forkName)
|
|
575
|
+
throw new Error("Unable to merge fork on main.");
|
|
576
|
+
this.refs.setFork(this.forkName);
|
|
577
|
+
this.refs.merge(ignore);
|
|
578
|
+
}
|
|
579
|
+
abortFork() {
|
|
580
|
+
if (!this.forkName)
|
|
581
|
+
throw new Error("Unable to abord fork on main.");
|
|
582
|
+
this.refs.setFork(this.forkName);
|
|
583
|
+
this.refs.abortFork();
|
|
584
|
+
}
|
|
585
|
+
closeResourceStreams(streams) {
|
|
586
|
+
this.refs.setFork(this.forkName);
|
|
587
|
+
const errorHdl = this.refs.runWithGC(() => {
|
|
588
|
+
return this.refs.binding.SkipRuntime_Runtime__closeResourceStreams(this.refs.json().exportJSON(streams));
|
|
589
|
+
});
|
|
590
|
+
if (errorHdl)
|
|
591
|
+
throw this.refs.handles.deleteHandle(errorHdl);
|
|
592
|
+
}
|
|
419
593
|
}
|
|
420
594
|
class ValuesImpl {
|
|
421
595
|
constructor(skjson, binding, pointer) {
|
|
@@ -486,6 +660,8 @@ export class ToBinding {
|
|
|
486
660
|
this.getError = getError;
|
|
487
661
|
this.stack = new Stack();
|
|
488
662
|
this.handles = new Handles();
|
|
663
|
+
this.forkName = null;
|
|
664
|
+
this.changes = null;
|
|
489
665
|
}
|
|
490
666
|
register(v) {
|
|
491
667
|
return this.handles.register(v);
|
|
@@ -505,14 +681,33 @@ export class ToBinding {
|
|
|
505
681
|
SkipRuntime_getContext() {
|
|
506
682
|
return this.stack.get();
|
|
507
683
|
}
|
|
684
|
+
SkipRuntime_getFork() {
|
|
685
|
+
return this.forkName;
|
|
686
|
+
}
|
|
687
|
+
SkipRuntime_getChangeManager() {
|
|
688
|
+
return this.changes ?? 0;
|
|
689
|
+
}
|
|
690
|
+
setFork(name) {
|
|
691
|
+
this.forkName = name;
|
|
692
|
+
}
|
|
508
693
|
// Mapper
|
|
509
694
|
SkipRuntime_Mapper__mapEntry(skmapper, key, values) {
|
|
510
695
|
const skjson = this.getJsonConverter();
|
|
511
696
|
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);
|
|
697
|
+
const context = new ContextImpl(this);
|
|
698
|
+
const result = mapper.object.mapEntry(skjson.importJSON(key), new ValuesImpl(skjson, this.binding, values), context);
|
|
514
699
|
return skjson.exportJSON(Array.from(result));
|
|
515
700
|
}
|
|
701
|
+
SkipRuntime_Mapper__getInfo(skmapper) {
|
|
702
|
+
return this.getInfo(skmapper);
|
|
703
|
+
}
|
|
704
|
+
SkipRuntime_Mapper__isEquals(mapper, other) {
|
|
705
|
+
const object = this.handles.get(mapper);
|
|
706
|
+
if (this.getChanges()?.needMapperReload(object.name)) {
|
|
707
|
+
return 0;
|
|
708
|
+
}
|
|
709
|
+
return this.isEquals(mapper, other);
|
|
710
|
+
}
|
|
516
711
|
SkipRuntime_deleteMapper(mapper) {
|
|
517
712
|
this.handles.deleteHandle(mapper);
|
|
518
713
|
}
|
|
@@ -520,9 +715,20 @@ export class ToBinding {
|
|
|
520
715
|
SkipRuntime_LazyCompute__compute(sklazyCompute, self, skkey) {
|
|
521
716
|
const skjson = this.getJsonConverter();
|
|
522
717
|
const lazyCompute = this.handles.get(sklazyCompute);
|
|
523
|
-
const
|
|
718
|
+
const context = new ContextImpl(this);
|
|
719
|
+
const result = lazyCompute.object.compute(new LazyCollectionImpl(self, this), skjson.importJSON(skkey), context);
|
|
524
720
|
return skjson.exportJSON(Array.from(result));
|
|
525
721
|
}
|
|
722
|
+
SkipRuntime_LazyCompute__getInfo(lazyCompute) {
|
|
723
|
+
return this.getInfo(lazyCompute);
|
|
724
|
+
}
|
|
725
|
+
SkipRuntime_LazyCompute__isEquals(lazyCompute, other) {
|
|
726
|
+
const object = this.handles.get(lazyCompute);
|
|
727
|
+
if (this.getChanges()?.needLazyComputeReload(object.name)) {
|
|
728
|
+
return 0;
|
|
729
|
+
}
|
|
730
|
+
return this.isEquals(lazyCompute, other);
|
|
731
|
+
}
|
|
526
732
|
SkipRuntime_deleteLazyCompute(lazyCompute) {
|
|
527
733
|
this.handles.deleteHandle(lazyCompute);
|
|
528
734
|
}
|
|
@@ -532,46 +738,83 @@ export class ToBinding {
|
|
|
532
738
|
const resource = this.handles.get(skresource);
|
|
533
739
|
const collections = {};
|
|
534
740
|
const keysIds = skjson.importJSON(skcollections);
|
|
535
|
-
const refs = this.refs();
|
|
536
741
|
for (const [key, name] of Object.entries(keysIds)) {
|
|
537
|
-
collections[key] = new EagerCollectionImpl(name,
|
|
742
|
+
collections[key] = new EagerCollectionImpl(name, this);
|
|
538
743
|
}
|
|
539
|
-
const collection = resource.instantiate(collections, new ContextImpl(
|
|
744
|
+
const collection = resource.instantiate(collections, new ContextImpl(this));
|
|
540
745
|
return EagerCollectionImpl.getName(collection);
|
|
541
746
|
}
|
|
542
747
|
SkipRuntime_deleteResource(resource) {
|
|
543
748
|
this.handles.deleteHandle(resource);
|
|
544
749
|
}
|
|
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) {
|
|
750
|
+
// ServiceDefinition
|
|
751
|
+
SkipRuntime_ServiceDefinition__createGraph(skservice, skcollections) {
|
|
557
752
|
const skjson = this.getJsonConverter();
|
|
558
753
|
const service = this.handles.get(skservice);
|
|
559
754
|
const collections = {};
|
|
560
755
|
const keysIds = skjson.importJSON(skcollections);
|
|
561
|
-
const refs = this.refs();
|
|
562
756
|
for (const [key, name] of Object.entries(keysIds)) {
|
|
563
|
-
collections[key] = new EagerCollectionImpl(name,
|
|
757
|
+
collections[key] = new EagerCollectionImpl(name, this);
|
|
564
758
|
}
|
|
565
|
-
const result = service.createGraph(collections, new ContextImpl(
|
|
759
|
+
const result = service.createGraph(collections, new ContextImpl(this));
|
|
566
760
|
const collectionsNames = {};
|
|
567
761
|
for (const [name, collection] of Object.entries(result)) {
|
|
568
762
|
collectionsNames[name] = EagerCollectionImpl.getName(collection);
|
|
569
763
|
}
|
|
570
764
|
return skjson.exportJSON(collectionsNames);
|
|
571
765
|
}
|
|
766
|
+
SkipRuntime_ServiceDefinition__inputs(skservice) {
|
|
767
|
+
const skjson = this.getJsonConverter();
|
|
768
|
+
const service = this.handles.get(skservice);
|
|
769
|
+
return skjson.exportJSON(service.inputs());
|
|
770
|
+
}
|
|
771
|
+
SkipRuntime_ServiceDefinition__resources(skservice) {
|
|
772
|
+
const skjson = this.getJsonConverter();
|
|
773
|
+
const service = this.handles.get(skservice);
|
|
774
|
+
return skjson.exportJSON(service.resources());
|
|
775
|
+
}
|
|
776
|
+
SkipRuntime_ServiceDefinition__initialData(skservice, name) {
|
|
777
|
+
const skjson = this.getJsonConverter();
|
|
778
|
+
const service = this.handles.get(skservice);
|
|
779
|
+
return skjson.exportJSON(service.initialData(name));
|
|
780
|
+
}
|
|
781
|
+
SkipRuntime_ServiceDefinition__buildResource(skservice, name, skparams) {
|
|
782
|
+
const skjson = this.getJsonConverter();
|
|
783
|
+
const service = this.handles.get(skservice);
|
|
784
|
+
const resource = service.buildResource(name, skjson.importJSON(skparams));
|
|
785
|
+
return this.binding.SkipRuntime_createResource(this.handles.register(resource));
|
|
786
|
+
}
|
|
787
|
+
SkipRuntime_ServiceDefinition__subscribe(skservice, external, writerId, instance, resource, skparams) {
|
|
788
|
+
const skjson = this.getJsonConverter();
|
|
789
|
+
const service = this.handles.get(skservice);
|
|
790
|
+
const writer = new CollectionWriter(writerId, this, this.forkName);
|
|
791
|
+
const params = skjson.importJSON(skparams, true);
|
|
792
|
+
return this.handles.register(service.subscribe(external, writer, instance, resource, params));
|
|
793
|
+
}
|
|
794
|
+
SkipRuntime_ServiceDefinition__unsubscribe(skservice, external, instance) {
|
|
795
|
+
const service = this.handles.get(skservice);
|
|
796
|
+
service.unsubscribe(external, instance);
|
|
797
|
+
}
|
|
798
|
+
SkipRuntime_ServiceDefinition__shutdown(skservice) {
|
|
799
|
+
const service = this.handles.get(skservice);
|
|
800
|
+
return this.handles.register(service.shutdown());
|
|
801
|
+
}
|
|
572
802
|
SkipRuntime_deleteService(service) {
|
|
573
803
|
this.handles.deleteHandle(service);
|
|
574
804
|
}
|
|
805
|
+
// Change manager
|
|
806
|
+
SkipRuntime_ChangeManager__needInputReload(skmanager, name) {
|
|
807
|
+
const manager = this.handles.get(skmanager);
|
|
808
|
+
return manager.needInputReload(name) ? 1 : 0;
|
|
809
|
+
}
|
|
810
|
+
SkipRuntime_ChangeManager__needResourceReload(skmanager, name) {
|
|
811
|
+
const manager = this.handles.get(skmanager);
|
|
812
|
+
return manager.needResourceReload(name);
|
|
813
|
+
}
|
|
814
|
+
SkipRuntime_ChangeManager__needExternalServiceReload(skmanager, name, resource) {
|
|
815
|
+
const manager = this.handles.get(skmanager);
|
|
816
|
+
return manager.needExternalServiceReload(name, resource) ? 1 : 0;
|
|
817
|
+
}
|
|
575
818
|
// Notifier
|
|
576
819
|
SkipRuntime_Notifier__subscribed(sknotifier) {
|
|
577
820
|
const notifier = this.handles.get(sknotifier);
|
|
@@ -596,88 +839,57 @@ export class ToBinding {
|
|
|
596
839
|
this.handles.deleteHandle(notifier);
|
|
597
840
|
}
|
|
598
841
|
// Reducer
|
|
599
|
-
|
|
842
|
+
SkipRuntime_Reducer__init(skreducer) {
|
|
600
843
|
const skjson = this.getJsonConverter();
|
|
601
844
|
const reducer = this.handles.get(skreducer);
|
|
602
|
-
return skjson.exportJSON(reducer.
|
|
845
|
+
return skjson.exportJSON(reducer.object.initial);
|
|
603
846
|
}
|
|
604
|
-
|
|
847
|
+
SkipRuntime_Reducer__add(skreducer, skacc, skvalue) {
|
|
605
848
|
const skjson = this.getJsonConverter();
|
|
606
849
|
const reducer = this.handles.get(skreducer);
|
|
607
|
-
return skjson.exportJSON(reducer.
|
|
850
|
+
return skjson.exportJSON(reducer.object.add(skacc ? skjson.importJSON(skacc) : null, skjson.importJSON(skvalue)));
|
|
608
851
|
}
|
|
609
|
-
|
|
610
|
-
this.handles.deleteHandle(reducer);
|
|
611
|
-
}
|
|
612
|
-
// ExternalService
|
|
613
|
-
SkipRuntime_ExternalService__subscribe(sksupplier, writerId, instance, resource, skparams) {
|
|
852
|
+
SkipRuntime_Reducer__remove(skreducer, skacc, skvalue) {
|
|
614
853
|
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());
|
|
854
|
+
const reducer = this.handles.get(skreducer);
|
|
855
|
+
return skjson.exportJSON(reducer.object.remove(skjson.importJSON(skacc), skjson.importJSON(skvalue)));
|
|
638
856
|
}
|
|
639
|
-
|
|
640
|
-
this.handles.
|
|
857
|
+
SkipRuntime_Reducer__isEquals(reducer, other) {
|
|
858
|
+
const object = this.handles.get(reducer);
|
|
859
|
+
if (this.getChanges()?.needReducerReload(object.name)) {
|
|
860
|
+
return 0;
|
|
861
|
+
}
|
|
862
|
+
return this.isEquals(reducer, other);
|
|
641
863
|
}
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
const checker = this.handles.get(skexecutor);
|
|
645
|
-
checker.resolve();
|
|
864
|
+
SkipRuntime_Reducer__getInfo(reducer) {
|
|
865
|
+
return this.getInfo(reducer);
|
|
646
866
|
}
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
checker.reject(this.handles.deleteHandle(error));
|
|
867
|
+
SkipRuntime_deleteReducer(reducer) {
|
|
868
|
+
this.handles.deleteHandle(reducer);
|
|
650
869
|
}
|
|
651
|
-
|
|
652
|
-
this.
|
|
870
|
+
async initService(service) {
|
|
871
|
+
this.setFork(null);
|
|
872
|
+
const uuid = crypto.randomUUID();
|
|
873
|
+
this.fork(uuid);
|
|
874
|
+
try {
|
|
875
|
+
this.setFork(uuid);
|
|
876
|
+
const definition = new ServiceDefinition(service);
|
|
877
|
+
await this.initService_(definition);
|
|
878
|
+
this.setFork(uuid);
|
|
879
|
+
this.merge();
|
|
880
|
+
return new ServiceInstance(this, null, definition);
|
|
881
|
+
}
|
|
882
|
+
catch (ex) {
|
|
883
|
+
this.setFork(uuid);
|
|
884
|
+
this.abortFork();
|
|
885
|
+
throw ex;
|
|
886
|
+
}
|
|
653
887
|
}
|
|
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));
|
|
888
|
+
initService_(definition) {
|
|
889
|
+
return this.runAsync(() => {
|
|
890
|
+
const skservicehHdl = this.handles.register(definition);
|
|
891
|
+
const skservice = this.binding.SkipRuntime_createService(skservicehHdl);
|
|
892
|
+
return this.binding.SkipRuntime_initService(skservice);
|
|
681
893
|
});
|
|
682
894
|
}
|
|
683
895
|
//
|
|
@@ -690,8 +902,132 @@ export class ToBinding {
|
|
|
690
902
|
needGC() {
|
|
691
903
|
return this.SkipRuntime_getContext() == null;
|
|
692
904
|
}
|
|
693
|
-
|
|
694
|
-
return
|
|
905
|
+
json() {
|
|
906
|
+
return this.getJsonConverter();
|
|
907
|
+
}
|
|
908
|
+
fork(name) {
|
|
909
|
+
const errorHdl = this.runWithGC(() => this.binding.SkipRuntime_Runtime__fork(name));
|
|
910
|
+
if (errorHdl)
|
|
911
|
+
throw this.handles.deleteHandle(errorHdl);
|
|
912
|
+
}
|
|
913
|
+
merge(ignore = []) {
|
|
914
|
+
const errorHdl = this.runWithGC(() => this.binding.SkipRuntime_Runtime__merge(this.json().exportJSON(ignore)));
|
|
915
|
+
if (errorHdl)
|
|
916
|
+
throw this.handles.deleteHandle(errorHdl);
|
|
917
|
+
}
|
|
918
|
+
abortFork() {
|
|
919
|
+
const errorHdl = this.runWithGC(() => this.binding.SkipRuntime_Runtime__abortFork());
|
|
920
|
+
if (errorHdl)
|
|
921
|
+
throw this.handles.deleteHandle(errorHdl);
|
|
922
|
+
}
|
|
923
|
+
async runAsync(fn) {
|
|
924
|
+
const result = this.runWithGC(() => {
|
|
925
|
+
return this.json().importJSON(fn(), true);
|
|
926
|
+
});
|
|
927
|
+
if (Array.isArray(result)) {
|
|
928
|
+
const handles = result;
|
|
929
|
+
const promises = handles.map((h) => this.handles.deleteHandle(h));
|
|
930
|
+
await Promise.all(promises);
|
|
931
|
+
}
|
|
932
|
+
else {
|
|
933
|
+
const errorHdl = result;
|
|
934
|
+
throw this.handles.deleteHandle(errorHdl);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
deepEquals(a, b) {
|
|
938
|
+
// Same reference or both NaN
|
|
939
|
+
if (a === b)
|
|
940
|
+
return true;
|
|
941
|
+
if (a !== a && b !== b)
|
|
942
|
+
return true; // NaN check
|
|
943
|
+
// Different types or one is null
|
|
944
|
+
if (typeof a !== typeof b || a === null || b === null)
|
|
945
|
+
return false;
|
|
946
|
+
// Primitives already checked by ===
|
|
947
|
+
if (typeof a !== "object" || typeof b !== "object")
|
|
948
|
+
return false;
|
|
949
|
+
// Arrays
|
|
950
|
+
if (Array.isArray(a)) {
|
|
951
|
+
if (!Array.isArray(b) || a.length !== b.length)
|
|
952
|
+
return false;
|
|
953
|
+
for (let i = 0; i < a.length; i++) {
|
|
954
|
+
if (!this.deepEquals(a[i], b[i]))
|
|
955
|
+
return false;
|
|
956
|
+
}
|
|
957
|
+
return true;
|
|
958
|
+
}
|
|
959
|
+
// Different array status
|
|
960
|
+
if (Array.isArray(b))
|
|
961
|
+
return false;
|
|
962
|
+
// Objects
|
|
963
|
+
const keysA = Object.keys(a);
|
|
964
|
+
const keysB = Object.keys(b);
|
|
965
|
+
if (keysA.length !== keysB.length)
|
|
966
|
+
return false;
|
|
967
|
+
for (const key of keysA) {
|
|
968
|
+
if (!Object.prototype.hasOwnProperty.call(b, key) ||
|
|
969
|
+
!this.deepEquals(a[key], b[key]))
|
|
970
|
+
return false;
|
|
971
|
+
}
|
|
972
|
+
return true;
|
|
973
|
+
}
|
|
974
|
+
getInfo(skmapper) {
|
|
975
|
+
const skjson = this.getJsonConverter();
|
|
976
|
+
const object = this.handles.get(skmapper);
|
|
977
|
+
const name = object.name;
|
|
978
|
+
const parameters = object.params.map((v) => {
|
|
979
|
+
if (v instanceof EagerCollectionImpl) {
|
|
980
|
+
return {
|
|
981
|
+
type: "collection",
|
|
982
|
+
value: v.collection,
|
|
983
|
+
};
|
|
984
|
+
}
|
|
985
|
+
if (v instanceof LazyCollectionImpl) {
|
|
986
|
+
return {
|
|
987
|
+
type: "collection",
|
|
988
|
+
value: v.lazyCollection,
|
|
989
|
+
};
|
|
990
|
+
}
|
|
991
|
+
return { type: "data", value: v };
|
|
992
|
+
});
|
|
993
|
+
return skjson.exportJSON({ name, parameters });
|
|
994
|
+
}
|
|
995
|
+
isEquals(mapper, other) {
|
|
996
|
+
const object = this.handles.get(mapper);
|
|
997
|
+
const oobject = this.handles.get(other);
|
|
998
|
+
if (object.object.constructor != oobject.object.constructor) {
|
|
999
|
+
return 0;
|
|
1000
|
+
}
|
|
1001
|
+
if (object.params.length != oobject.params.length)
|
|
1002
|
+
return 0;
|
|
1003
|
+
for (const [i, param] of object.params.entries()) {
|
|
1004
|
+
const oparam = oobject.params[i];
|
|
1005
|
+
if (param instanceof EagerCollectionImpl) {
|
|
1006
|
+
if (oparam instanceof EagerCollectionImpl) {
|
|
1007
|
+
if (param.collection != oparam.collection)
|
|
1008
|
+
return 0;
|
|
1009
|
+
}
|
|
1010
|
+
else {
|
|
1011
|
+
return 0;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
else if (param instanceof LazyCollectionImpl) {
|
|
1015
|
+
if (oparam instanceof LazyCollectionImpl) {
|
|
1016
|
+
if (param.lazyCollection != oparam.lazyCollection)
|
|
1017
|
+
return 0;
|
|
1018
|
+
}
|
|
1019
|
+
else {
|
|
1020
|
+
return 0;
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
else if (!this.deepEquals(param, oparam)) {
|
|
1024
|
+
return 0;
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
return 1;
|
|
1028
|
+
}
|
|
1029
|
+
getChanges() {
|
|
1030
|
+
return this.changes ? this.handles.get(this.changes) : null;
|
|
695
1031
|
}
|
|
696
1032
|
}
|
|
697
1033
|
//# sourceMappingURL=index.js.map
|