vrpc 3.0.0-alpha.3 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/LICENSE +1 -1
- package/README.md +8 -9
- package/browser/vrpc.js +1 -1
- package/package.json +8 -5
- package/vrpc/VrpcAdapter.js +194 -171
- package/vrpc/VrpcAgent.js +18 -17
- package/vrpc/VrpcClient.js +260 -113
- package/vrpc/VrpcNative.js +25 -2
- package/vrpc/adapter.hpp +4 -2
- package/vrpc/addon.cpp +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vrpc",
|
|
3
|
-
"version": "3.0.0
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Variadic Remote Procedure Calls",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"directories": {
|
|
@@ -12,10 +12,11 @@
|
|
|
12
12
|
"build:addon": "ln -sf binding.gyp.no-auto binding.gyp && node-gyp rebuild && rm binding.gyp",
|
|
13
13
|
"build:browser": "./node_modules/.bin/webpack",
|
|
14
14
|
"build:doc": "./node_modules/.bin/jsdoc2md -f vrpc/*.js --param-list-format=list --separators > docs/api.md",
|
|
15
|
-
"test": "npm run test:agent && npm run test:client && npm run test:
|
|
15
|
+
"test": "npm run test:adapter && npm run test:native && npm run test:agent && npm run test:client && npm run test:production",
|
|
16
|
+
"test:adapter": "./node_modules/.bin/mocha tests/adapter/*.js --exit",
|
|
17
|
+
"test:native": "./node_modules/.bin/mocha tests/native/*.js --exit",
|
|
16
18
|
"test:agent": "tests/agent/test.sh",
|
|
17
19
|
"test:client": "tests/client/test.sh",
|
|
18
|
-
"test:native": "./node_modules/.bin/mocha tests/native/vrpc-native*.js --exit",
|
|
19
20
|
"test:performance": "tests/performance/test.sh",
|
|
20
21
|
"test:production": "./node_modules/.bin/mocha tests/production/lifeCycleTest.js --timeout 30000 --exit && tests/production/test.sh"
|
|
21
22
|
},
|
|
@@ -49,7 +50,7 @@
|
|
|
49
50
|
"crypto-browserify": "^3.12.0",
|
|
50
51
|
"dockerode": "^3.2.0",
|
|
51
52
|
"jsdoc-to-markdown": "^7.0.1",
|
|
52
|
-
"mocha": "^
|
|
53
|
+
"mocha": "^9.1.3",
|
|
53
54
|
"os-browserify": "^0.3.0",
|
|
54
55
|
"sinon": "^7.3.2",
|
|
55
56
|
"stream-browserify": "^3.0.0",
|
|
@@ -66,8 +67,10 @@
|
|
|
66
67
|
"dependencies": {
|
|
67
68
|
"ajv": "^6.10.0",
|
|
68
69
|
"argparse": "^2.0.1",
|
|
70
|
+
"buffer": "^6.0.3",
|
|
69
71
|
"caller": "^1.0.1",
|
|
70
72
|
"mqtt": "^4.2.6",
|
|
71
|
-
"nanoid": "^3.1.23"
|
|
73
|
+
"nanoid": "^3.1.23",
|
|
74
|
+
"process": "^0.11.10"
|
|
72
75
|
}
|
|
73
76
|
}
|
package/vrpc/VrpcAdapter.js
CHANGED
|
@@ -16,7 +16,7 @@ Author: Dr. Burkhard C. Heisen (https://github.com/heisenware/vrpc)
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
|
19
|
-
Copyright (c) 2018 -
|
|
19
|
+
Copyright (c) 2018 - 2022 Dr. Burkhard C. Heisen <burkhard.heisen@heisenware.com>.
|
|
20
20
|
|
|
21
21
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
22
22
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -44,7 +44,7 @@ const Ajv = require('ajv')
|
|
|
44
44
|
const caller = require('caller')
|
|
45
45
|
const commentParser = require('./comment-parser')
|
|
46
46
|
const EventEmitter = require('events')
|
|
47
|
-
const {
|
|
47
|
+
const { nanoid } = require('nanoid')
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
50
|
* Generates an adapter layer for existing code and enables further VRPC-based
|
|
@@ -101,17 +101,20 @@ class VrpcAdapter {
|
|
|
101
101
|
* NOTE: This function currently only supports registration of classes (either
|
|
102
102
|
* when provided as object or when exported on the provided module path)
|
|
103
103
|
*/
|
|
104
|
-
|
|
104
|
+
static register (code, options = {}) {
|
|
105
105
|
if (typeof code === 'string') {
|
|
106
106
|
const absPath = path.resolve(caller(), '../', code)
|
|
107
107
|
const relPath = path.relative(__dirname, absPath)
|
|
108
|
-
const absJsdocPath =
|
|
108
|
+
const absJsdocPath =
|
|
109
|
+
absPath && absPath.endsWith('.js') ? absPath : `${absPath}.js`
|
|
109
110
|
const Klass = require(relPath)
|
|
110
111
|
this._registerClass(Klass, absJsdocPath, options)
|
|
111
112
|
} else {
|
|
112
113
|
const { jsdocPath } = options
|
|
114
|
+
const sJsdocPath =
|
|
115
|
+
jsdocPath && jsdocPath.endsWith('.js') ? jsdocPath : `${jsdocPath}.js`
|
|
113
116
|
if (jsdocPath) {
|
|
114
|
-
const absJsdocPath = path.resolve(caller(), '../',
|
|
117
|
+
const absJsdocPath = path.resolve(caller(), '../', sJsdocPath)
|
|
115
118
|
this._registerClass(code, absJsdocPath, { ...options, jsdoc: true })
|
|
116
119
|
} else {
|
|
117
120
|
this._registerClass(code, null, options)
|
|
@@ -147,14 +150,16 @@ class VrpcAdapter {
|
|
|
147
150
|
const content = fs.readFileSync(absJsdocPath).toString('utf8')
|
|
148
151
|
meta = this._parseComments(content)
|
|
149
152
|
}
|
|
150
|
-
VrpcAdapter._functionRegistry.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
153
|
+
if (!VrpcAdapter._functionRegistry.has(className)) {
|
|
154
|
+
VrpcAdapter._functionRegistry.set(className, {
|
|
155
|
+
memberFunctions,
|
|
156
|
+
meta,
|
|
157
|
+
Klass: {},
|
|
158
|
+
withNew: false,
|
|
159
|
+
staticFunctions: [],
|
|
160
|
+
schema: null
|
|
161
|
+
})
|
|
162
|
+
}
|
|
158
163
|
VrpcAdapter._instances.set(instance, {
|
|
159
164
|
className,
|
|
160
165
|
instance: obj,
|
|
@@ -162,81 +167,56 @@ class VrpcAdapter {
|
|
|
162
167
|
})
|
|
163
168
|
}
|
|
164
169
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
static getMemberFunctions (className) {
|
|
170
|
-
return JSON.stringify(VrpcAdapter._getMemberFunctionsArray(className))
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
static getStaticFunctions (className) {
|
|
174
|
-
return JSON.stringify(VrpcAdapter._getStaticFunctionsArray(className))
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
static getMetaData (className) {
|
|
178
|
-
return JSON.stringify(VrpcAdapter._getMetaData(className))
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
static getInstances (className) {
|
|
182
|
-
return JSON.stringify(VrpcAdapter._getInstancesArray(className))
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
static call (jsonString) {
|
|
186
|
-
const json = JSON.parse(jsonString)
|
|
187
|
-
VrpcAdapter._call(json)
|
|
188
|
-
return JSON.stringify(json)
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
static onCallback (callback) {
|
|
192
|
-
VrpcAdapter._callback = callback
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// convenience interface if used in parallel - as local factory and from remote
|
|
170
|
+
/*****************************************************
|
|
171
|
+
* convenience interface if used as plug-able factory *
|
|
172
|
+
******************************************************/
|
|
196
173
|
|
|
197
174
|
/**
|
|
198
|
-
* Creates
|
|
175
|
+
* Creates a new instance
|
|
199
176
|
*
|
|
200
|
-
* @param {
|
|
201
|
-
* @param
|
|
202
|
-
*
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
if (typeof className === 'object') {
|
|
209
|
-
if (className.instance) {
|
|
210
|
-
return VrpcAdapter._createNamed(
|
|
211
|
-
className.className,
|
|
212
|
-
className.instance,
|
|
213
|
-
...className.args
|
|
214
|
-
)
|
|
215
|
-
}
|
|
216
|
-
return VrpcAdapter._create(className.className, ...className.args)
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Creates a managed named instance
|
|
222
|
-
*
|
|
223
|
-
* @param {String} className Name of the class to create an instance of
|
|
224
|
-
* @param {String} instance Name of the instance
|
|
225
|
-
* @param {...any} args Arguments to provide to the constructor
|
|
177
|
+
* @param {Object} options
|
|
178
|
+
* @param {String} options.className Name of the class which should be
|
|
179
|
+
* instantiated
|
|
180
|
+
* @param {String} [options.instance] Name of the created instance. If not
|
|
181
|
+
* provided an id will be generated
|
|
182
|
+
* @param {Array} [options.args] Positional arguments for the constructor call
|
|
183
|
+
* @param {bool} [options.isIsolated=false] If true the created instance will
|
|
184
|
+
* be visible only to the client who created it
|
|
226
185
|
* @returns {Object} The real instance (not a proxy!)
|
|
227
186
|
*/
|
|
228
|
-
static
|
|
229
|
-
|
|
187
|
+
static create ({
|
|
188
|
+
className,
|
|
189
|
+
instance = nanoid(8),
|
|
190
|
+
args = [],
|
|
191
|
+
isIsolated = false
|
|
192
|
+
} = {}) {
|
|
193
|
+
const json = { c: className, a: [instance, ...args] }
|
|
194
|
+
const obj = isIsolated
|
|
195
|
+
? VrpcAdapter._handleCreateIsolated(json)
|
|
196
|
+
: VrpcAdapter._handleCreateShared(json)
|
|
197
|
+
if (json.e) throw new Error(json.e)
|
|
198
|
+
return obj
|
|
230
199
|
}
|
|
231
200
|
|
|
232
201
|
/**
|
|
233
|
-
* Deletes
|
|
202
|
+
* Deletes an instance
|
|
234
203
|
*
|
|
235
|
-
* @param {String} instance
|
|
204
|
+
* @param {String|Object} instance Instance (name or object itself) to be deleted
|
|
236
205
|
* @returns {Boolean} True in case of success, false otherwise
|
|
237
206
|
*/
|
|
238
207
|
static delete (instance) {
|
|
239
|
-
|
|
208
|
+
if (typeof instance === 'string') {
|
|
209
|
+
return VrpcAdapter._delete(instance)
|
|
210
|
+
}
|
|
211
|
+
if (typeof instance === 'object') {
|
|
212
|
+
for (const [k, v] of VrpcAdapter._instances) {
|
|
213
|
+
if (v.instance === instance) {
|
|
214
|
+
VrpcAdapter._instances.delete(k)
|
|
215
|
+
return true
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return false
|
|
219
|
+
}
|
|
240
220
|
}
|
|
241
221
|
|
|
242
222
|
/**
|
|
@@ -270,34 +250,14 @@ class VrpcAdapter {
|
|
|
270
250
|
return VrpcAdapter._getInstancesArray(className)
|
|
271
251
|
}
|
|
272
252
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
* @return {Array.<String>} Array of member function names
|
|
278
|
-
*/
|
|
279
|
-
static getAvailableMemberFunctions (className) {
|
|
280
|
-
return VrpcAdapter._getMemberFunctionsArray(className)
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Provides all available static functions of a registered class.
|
|
285
|
-
*
|
|
286
|
-
* @param {String} className Name of class to provide static functions for
|
|
287
|
-
* @returns {Array.<String>} Array of static function names
|
|
288
|
-
*/
|
|
289
|
-
static getAvailableStaticFunctions (className) {
|
|
290
|
-
return VrpcAdapter._getStaticFunctionsArray(className)
|
|
253
|
+
static call (jsonString) {
|
|
254
|
+
const json = JSON.parse(jsonString)
|
|
255
|
+
VrpcAdapter._call(json)
|
|
256
|
+
return JSON.stringify(json)
|
|
291
257
|
}
|
|
292
258
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
*
|
|
296
|
-
* @param {String} className Name of class to provide meta data for
|
|
297
|
-
* @returns {MetaData} Meta Data
|
|
298
|
-
*/
|
|
299
|
-
static getAvailableMetaData (className) {
|
|
300
|
-
return VrpcAdapter._getMetaData(className)
|
|
259
|
+
static onCallback (callback) {
|
|
260
|
+
VrpcAdapter._callback = callback
|
|
301
261
|
}
|
|
302
262
|
|
|
303
263
|
/**
|
|
@@ -445,6 +405,7 @@ class VrpcAdapter {
|
|
|
445
405
|
VrpcAdapter._handleDelete(json)
|
|
446
406
|
break
|
|
447
407
|
default:
|
|
408
|
+
// this call may have the side-effect of taking a listener on board
|
|
448
409
|
VrpcAdapter._handleCall(json)
|
|
449
410
|
}
|
|
450
411
|
const after = Object.keys(VrpcAdapter._listeners).length
|
|
@@ -454,26 +415,35 @@ class VrpcAdapter {
|
|
|
454
415
|
}
|
|
455
416
|
|
|
456
417
|
static _handleCreateIsolated (json) {
|
|
418
|
+
let instance
|
|
457
419
|
try {
|
|
458
420
|
const className = json.c
|
|
459
421
|
const [instanceId, ...args] = json.a
|
|
460
|
-
|
|
422
|
+
instance = VrpcAdapter._create(className, instanceId, ...args)
|
|
461
423
|
VrpcAdapter._instances.set(instanceId, {
|
|
462
424
|
instance,
|
|
463
425
|
className,
|
|
464
426
|
isIsolated: true
|
|
465
427
|
})
|
|
428
|
+
VrpcAdapter._emitter.emit('create', {
|
|
429
|
+
args,
|
|
430
|
+
className,
|
|
431
|
+
isIsolated: true,
|
|
432
|
+
instance: instanceId
|
|
433
|
+
})
|
|
466
434
|
json.r = instanceId
|
|
467
435
|
} catch (err) {
|
|
468
436
|
json.e = err.message
|
|
469
437
|
}
|
|
438
|
+
return instance
|
|
470
439
|
}
|
|
471
440
|
|
|
472
441
|
static _handleCreateShared (json) {
|
|
442
|
+
let instance
|
|
473
443
|
try {
|
|
474
444
|
const className = json.c
|
|
475
445
|
const [instanceId, ...args] = json.a
|
|
476
|
-
|
|
446
|
+
instance = VrpcAdapter._create(className, instanceId, ...args)
|
|
477
447
|
VrpcAdapter._instances.set(instanceId, {
|
|
478
448
|
instance,
|
|
479
449
|
className,
|
|
@@ -483,11 +453,13 @@ class VrpcAdapter {
|
|
|
483
453
|
VrpcAdapter._emitter.emit('create', {
|
|
484
454
|
args,
|
|
485
455
|
className,
|
|
456
|
+
isIsolated: false,
|
|
486
457
|
instance: instanceId
|
|
487
458
|
})
|
|
488
459
|
} catch (err) {
|
|
489
460
|
json.e = err.message
|
|
490
461
|
}
|
|
462
|
+
return instance
|
|
491
463
|
}
|
|
492
464
|
|
|
493
465
|
static _handleCallAll (json) {
|
|
@@ -499,13 +471,15 @@ class VrpcAdapter {
|
|
|
499
471
|
] of VrpcAdapter._instances) {
|
|
500
472
|
// TODO Think about a configurable behavior w.r.t. isolated instances...
|
|
501
473
|
if (className !== json.c || isIsolated) continue
|
|
502
|
-
let v
|
|
474
|
+
let v = true
|
|
503
475
|
let e = null
|
|
504
476
|
try {
|
|
505
|
-
const
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
477
|
+
const unwrapped = VrpcAdapter._unwrapArguments(json, id)
|
|
478
|
+
if (unwrapped) {
|
|
479
|
+
const funcName = unwrapped[0]
|
|
480
|
+
v = instance[funcName].apply(instance, unwrapped.slice(1))
|
|
481
|
+
v = VrpcAdapter.sanitizeEventListenerReturnValues(v)
|
|
482
|
+
}
|
|
509
483
|
} catch (err) {
|
|
510
484
|
e = err.message
|
|
511
485
|
}
|
|
@@ -535,12 +509,11 @@ class VrpcAdapter {
|
|
|
535
509
|
|
|
536
510
|
static _handleDelete (json) {
|
|
537
511
|
try {
|
|
538
|
-
const
|
|
539
|
-
|
|
540
|
-
json.r = VrpcAdapter._delete(instanceId)
|
|
512
|
+
const instance = json.a[0] // first arg is instance to be deleted
|
|
513
|
+
json.r = VrpcAdapter._delete(instance)
|
|
541
514
|
VrpcAdapter._emitter.emit('delete', {
|
|
542
|
-
|
|
543
|
-
|
|
515
|
+
instance,
|
|
516
|
+
className: json.c
|
|
544
517
|
})
|
|
545
518
|
} catch (err) {
|
|
546
519
|
json.e = err.message
|
|
@@ -548,7 +521,18 @@ class VrpcAdapter {
|
|
|
548
521
|
}
|
|
549
522
|
|
|
550
523
|
static _handleCall (json) {
|
|
551
|
-
|
|
524
|
+
// special case: removeAllListeners
|
|
525
|
+
if (json.f === 'removeAllListeners') {
|
|
526
|
+
VrpcAdapter._removeAllListeners(json.a[0], json.s, json.c)
|
|
527
|
+
json.r = true
|
|
528
|
+
return
|
|
529
|
+
}
|
|
530
|
+
const unwrapped = VrpcAdapter._unwrapArguments(json)
|
|
531
|
+
if (!unwrapped) {
|
|
532
|
+
// this call must be skipped (event emitter stuff)
|
|
533
|
+
json.r = true
|
|
534
|
+
return
|
|
535
|
+
}
|
|
552
536
|
// Check whether context is a registered class
|
|
553
537
|
const entry = VrpcAdapter._functionRegistry.get(json.c)
|
|
554
538
|
if (entry !== undefined) {
|
|
@@ -560,7 +544,7 @@ class VrpcAdapter {
|
|
|
560
544
|
// subscription against all functions
|
|
561
545
|
if (VrpcAdapter._isFunction(Klass[json.f])) {
|
|
562
546
|
try {
|
|
563
|
-
const ret = Klass[json.f].apply(null,
|
|
547
|
+
const ret = Klass[json.f].apply(null, unwrapped)
|
|
564
548
|
// check if function returns promise
|
|
565
549
|
if (VrpcAdapter._isPromise(ret)) {
|
|
566
550
|
this._handlePromise(json, ret)
|
|
@@ -578,7 +562,7 @@ class VrpcAdapter {
|
|
|
578
562
|
const { instance } = entry
|
|
579
563
|
if (VrpcAdapter._isFunction(instance[json.f])) {
|
|
580
564
|
try {
|
|
581
|
-
let ret = instance[json.f].apply(instance,
|
|
565
|
+
let ret = instance[json.f].apply(instance, unwrapped)
|
|
582
566
|
ret = VrpcAdapter.sanitizeEventListenerReturnValues(ret)
|
|
583
567
|
// check if function returns promise
|
|
584
568
|
if (VrpcAdapter._isPromise(ret)) {
|
|
@@ -605,31 +589,35 @@ class VrpcAdapter {
|
|
|
605
589
|
static _delete (instanceId) {
|
|
606
590
|
const entry = VrpcAdapter._instances.get(instanceId)
|
|
607
591
|
if (entry) {
|
|
592
|
+
// in case the instance was an EventEmitter, free all registered listeners
|
|
593
|
+
if (VrpcAdapter._isFunction(entry.removeAllListeners)) {
|
|
594
|
+
entry.removeAllListeners()
|
|
595
|
+
}
|
|
596
|
+
for (const [key, { clients, instance }] of Object.entries(
|
|
597
|
+
VrpcAdapter._listeners
|
|
598
|
+
)) {
|
|
599
|
+
if (instance === instanceId) {
|
|
600
|
+
VrpcAdapter._listeners[key] = { clients }
|
|
601
|
+
}
|
|
602
|
+
}
|
|
608
603
|
VrpcAdapter._instances.delete(instanceId)
|
|
609
604
|
return true
|
|
610
605
|
}
|
|
611
606
|
return false
|
|
612
607
|
}
|
|
613
608
|
|
|
614
|
-
static
|
|
615
|
-
const listeners = VrpcAdapter._listeners[clientId]
|
|
616
|
-
if (listeners) {
|
|
617
|
-
listeners.forEach(({ i, e, f }) => {
|
|
618
|
-
VrpcAdapter.getInstance(i).removeListener(e, f)
|
|
619
|
-
})
|
|
620
|
-
}
|
|
621
|
-
delete VrpcAdapter._listeners[clientId]
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
static _unregisterEventListenersOfInstance (instance) {
|
|
609
|
+
static _unregisterClient (clientId) {
|
|
625
610
|
for (const [key, value] of Object.entries(VrpcAdapter._listeners)) {
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
611
|
+
const { instance, event, listener, clients } = value
|
|
612
|
+
const filteredClients = clients.filter(x => x !== clientId)
|
|
613
|
+
if (filteredClients.length === 0) {
|
|
614
|
+
if (event) {
|
|
615
|
+
VrpcAdapter.getInstance(instance).removeListener(event, listener)
|
|
630
616
|
}
|
|
631
|
-
|
|
632
|
-
}
|
|
617
|
+
delete VrpcAdapter._listeners[key]
|
|
618
|
+
} else {
|
|
619
|
+
VrpcAdapter._listeners[key].clients = filteredClients
|
|
620
|
+
}
|
|
633
621
|
}
|
|
634
622
|
}
|
|
635
623
|
|
|
@@ -641,51 +629,86 @@ class VrpcAdapter {
|
|
|
641
629
|
if (!valid) throw new Error(VrpcAdapter._ajv.errorsText())
|
|
642
630
|
}
|
|
643
631
|
|
|
644
|
-
static
|
|
632
|
+
static _unwrapArguments (json, instanceId) {
|
|
645
633
|
const { f: func, s: sender, a: args, c: context } = json
|
|
646
|
-
const
|
|
647
|
-
|
|
648
|
-
//
|
|
649
|
-
if (typeof arg === 'string' && arg.
|
|
650
|
-
const
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
//
|
|
656
|
-
if (
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
634
|
+
const unwrapped = []
|
|
635
|
+
for (const arg of args) {
|
|
636
|
+
// find those args that actually need to be functions
|
|
637
|
+
if (typeof arg === 'string' && arg.slice(0, 5) === '__f__') {
|
|
638
|
+
const callback = this._generateCallback(arg, json, instanceId)
|
|
639
|
+
unwrapped.push(callback)
|
|
640
|
+
} else if (typeof arg === 'string' && arg.slice(0, 5) === '__e__') {
|
|
641
|
+
const listener = this._generateListener(arg, json, instanceId)
|
|
642
|
+
unwrapped.push(listener)
|
|
643
|
+
// start tracking clients that are registering event listeners
|
|
644
|
+
if (!VrpcAdapter._listeners[arg]) {
|
|
645
|
+
VrpcAdapter._listeners[arg] = {
|
|
646
|
+
listener,
|
|
647
|
+
clients: [sender],
|
|
648
|
+
instance: context,
|
|
649
|
+
event: null
|
|
650
|
+
}
|
|
651
|
+
} else {
|
|
652
|
+
VrpcAdapter._listeners[arg].clients.push(sender)
|
|
653
|
+
}
|
|
654
|
+
// see whether the requested listener is an EventEmitter registration
|
|
655
|
+
if (func === 'on' || func === 'addListener') {
|
|
656
|
+
// if this event is already registered avoid a second registration
|
|
657
|
+
if (VrpcAdapter._listeners[arg].event) {
|
|
658
|
+
return null // means that this call won't be forwarded
|
|
659
|
+
}
|
|
660
|
+
VrpcAdapter._listeners[arg].event = args[0]
|
|
661
661
|
}
|
|
662
|
-
if (
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
VrpcAdapter.getInstance(
|
|
662
|
+
if (func === 'off' || func === 'removeListener') {
|
|
663
|
+
const { clients, listener, event } = VrpcAdapter._listeners[arg]
|
|
664
|
+
const filteredClients = clients.filter(x => x !== sender)
|
|
665
|
+
// don't unregister this event, as other clients are still listening
|
|
666
|
+
if (filteredClients.length > 0) {
|
|
667
|
+
VrpcAdapter._listeners[arg].clients = filteredClients
|
|
668
|
+
} else {
|
|
669
|
+
delete VrpcAdapter._listeners[arg]
|
|
670
|
+
VrpcAdapter.getInstance(context).off(event, listener)
|
|
671
671
|
}
|
|
672
|
+
return null // means that this call won't be forwarded
|
|
672
673
|
}
|
|
673
674
|
} else {
|
|
674
|
-
//
|
|
675
|
-
|
|
675
|
+
// default behavior is to not touch
|
|
676
|
+
unwrapped.push(arg)
|
|
676
677
|
}
|
|
677
|
-
}
|
|
678
|
-
return
|
|
678
|
+
}
|
|
679
|
+
return unwrapped
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
static _removeAllListeners (event, sender, context) {
|
|
683
|
+
for (const [key, value] of Object.entries(VrpcAdapter._listeners)) {
|
|
684
|
+
if (value.event === event) {
|
|
685
|
+
const filteredClients = value.clients.filter(x => x !== sender)
|
|
686
|
+
if (filteredClients.length > 0) {
|
|
687
|
+
VrpcAdapter._listeners[key].clients = filteredClients
|
|
688
|
+
} else {
|
|
689
|
+
delete VrpcAdapter._listeners[key]
|
|
690
|
+
VrpcAdapter.getInstance(context).off(event, value.listener)
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
static _generateCallback (id, json, instanceId) {
|
|
697
|
+
return (...innerArgs) => {
|
|
698
|
+
// callAll expects the instanceId as first argument
|
|
699
|
+
const a = instanceId ? [instanceId, ...innerArgs] : [...innerArgs]
|
|
700
|
+
VrpcAdapter._callback({ a, s: json.s, i: id })
|
|
701
|
+
}
|
|
679
702
|
}
|
|
680
703
|
|
|
681
|
-
static
|
|
682
|
-
|
|
683
|
-
// do not even
|
|
684
|
-
if (
|
|
704
|
+
static _generateListener (id, json, instanceId) {
|
|
705
|
+
return (...innerArgs) => {
|
|
706
|
+
// do not even emit for already offline clients
|
|
707
|
+
if (!VrpcAdapter._listeners[id]) return
|
|
708
|
+
// callAll expects the instanceId as first argument
|
|
685
709
|
const a = instanceId ? [instanceId, ...innerArgs] : [...innerArgs]
|
|
686
|
-
VrpcAdapter._callback({ a, s: json.s,
|
|
710
|
+
VrpcAdapter._callback({ a, s: json.s, i: id })
|
|
687
711
|
}
|
|
688
|
-
return wrapper
|
|
689
712
|
}
|
|
690
713
|
|
|
691
714
|
static _handlePromise (json, promise) {
|
|
@@ -812,7 +835,7 @@ class VrpcAdapter {
|
|
|
812
835
|
/**
|
|
813
836
|
* Event 'create'
|
|
814
837
|
*
|
|
815
|
-
* Emitted on creation of
|
|
838
|
+
* Emitted on creation of shared instance
|
|
816
839
|
*
|
|
817
840
|
* @event VrpcAdapter#create
|
|
818
841
|
* @type {Object}
|
|
@@ -824,7 +847,7 @@ class VrpcAdapter {
|
|
|
824
847
|
/**
|
|
825
848
|
* Event 'delete'
|
|
826
849
|
*
|
|
827
|
-
* Emitted on deletion of
|
|
850
|
+
* Emitted on deletion of shared instance
|
|
828
851
|
*
|
|
829
852
|
* @event VrpcAdapter#delete
|
|
830
853
|
* @type {Object}
|