vrpc 3.0.0-alpha.3 → 3.0.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vrpc",
3
- "version": "3.0.0-alpha.3",
3
+ "version": "3.0.3",
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:native",
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": "^6.1.4",
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
  }
@@ -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 - 2021 Dr. Burkhard C. Heisen <burkhard.heisen@heisenware.com>.
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 { type } = require('os')
47
+ const { nanoid } = require('nanoid')
48
48
 
49
49
  /**
50
50
  * Generates an adapter layer for existing code and enables further VRPC-based
@@ -105,13 +105,16 @@ class VrpcAdapter {
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 = `${absPath}.js`
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(), '../', `${jsdocPath}.js`)
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.set(className, {
151
- memberFunctions,
152
- meta,
153
- Klass: {},
154
- withNew: false,
155
- staticFunctions: [],
156
- schema: null
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
- static getClasses () {
166
- return JSON.stringify(VrpcAdapter._getClassesArray())
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
196
-
197
- /**
198
- * Creates an un-managed, anonymous instance
199
- *
200
- * @param {String} className Name of the class to create an instance of
201
- * @param {...any} args Arguments to provide to the constructor
202
- * @returns {Object} The real instance (not a proxy!)
203
- */
204
- static create (className, ...args) {
205
- if (typeof className === 'string') {
206
- return VrpcAdapter._create(className, ...args)
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
- }
170
+ /*****************************************************
171
+ * convenience interface if used as plug-able factory *
172
+ ******************************************************/
219
173
 
220
174
  /**
221
- * Creates a managed named instance
175
+ * Creates a new instance
222
176
  *
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 createNamed (className, instance, ...args) {
229
- return VrpcAdapter._createNamed(className, instance, ...args)
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 a managed instance
202
+ * Deletes an instance
234
203
  *
235
- * @param {String} instance Name of the instance to be deleted
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
- return VrpcAdapter._delete(instance)
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
- * Provides all available member functions of the specified class.
275
- *
276
- * @param {String} className Name of class to provide member functions for
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
- * Provides all available meta data of the registered class.
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
- const instance = VrpcAdapter._create(className, instanceId, ...args)
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
- const instance = VrpcAdapter._create(className, instanceId, ...args)
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 wrappedArgs = VrpcAdapter._wrapArguments(json, id)
506
- const funcName = wrappedArgs[0]
507
- v = instance[funcName].apply(instance, wrappedArgs.slice(1))
508
- v = VrpcAdapter.sanitizeEventListenerReturnValues(v)
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 wrappedArgs = VrpcAdapter._wrapArguments(json)
539
- const instanceId = wrappedArgs[0]
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
- className: json.c,
543
- instance: wrappedArgs[0]
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
- const wrappedArgs = VrpcAdapter._wrapArguments(json)
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, wrappedArgs)
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, wrappedArgs)
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 _unregisterEventListeners (clientId) {
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
- VrpcAdapter._listeners[key] = value.filter(({ i, e, f }) => {
627
- if (instance === i) {
628
- VrpcAdapter.getInstance(i).removeListener(e, f)
629
- return false
611
+ const { instances, event, listener, clients } = value
612
+ clients.delete(clientId)
613
+ if (clients.size === 0) {
614
+ if (event) {
615
+ instances.forEach(instance => {
616
+ VrpcAdapter.getInstance(instance).removeListener(event, listener)
617
+ })
630
618
  }
631
- return true
632
- })
619
+ delete VrpcAdapter._listeners[key]
620
+ }
633
621
  }
634
622
  }
635
623
 
@@ -641,51 +629,101 @@ class VrpcAdapter {
641
629
  if (!valid) throw new Error(VrpcAdapter._ajv.errorsText())
642
630
  }
643
631
 
644
- static _wrapArguments (json, instanceId) {
645
- const { f: func, s: sender, a: args, c: context } = json
646
- const wrapped = []
647
- args.forEach(arg => {
648
- // Find those args that actually need to be function callbacks
649
- if (typeof arg === 'string' && arg.substr(0, 5) === '__f__') {
650
- const f = this._generateWrapper(arg, json, instanceId)
651
- wrapped.push(f)
652
- if (!sender) return
653
- // Register this client to later know when he is dead and skip callbacks
654
- if (!VrpcAdapter._listeners[sender]) VrpcAdapter._listeners[sender] = []
655
- // Check whether injected callback is an EventEmitter registration
656
- if (func === 'on' && typeof args[0] === 'string') {
657
- const e = args[0]
658
- const i = context
659
- const r = arg
660
- VrpcAdapter._listeners[sender].push({ i, e, f, r })
632
+ static _unwrapArguments (json, instanceId) {
633
+ const sender = json.s
634
+ let context = json.c
635
+ let func = json.f
636
+ let args = json.a
637
+ // things are different if we came from callAll (instanceId !== undefined)
638
+ if (instanceId) {
639
+ context = instanceId
640
+ func = args[0]
641
+ args = args.slice(1)
642
+ }
643
+ const unwrapped = instanceId ? [func] : []
644
+ for (const arg of args) {
645
+ // find those args that actually need to be functions
646
+ if (typeof arg === 'string' && arg.slice(0, 5) === '__f__') {
647
+ const callback = this._generateCallback(arg, sender, instanceId)
648
+ unwrapped.push(callback)
649
+ } else if (typeof arg === 'string' && arg.slice(0, 5) === '__e__') {
650
+ const listener = this._generateListener(arg, sender, instanceId)
651
+ unwrapped.push(listener)
652
+ // start tracking clients that are registering event listeners
653
+ if (!VrpcAdapter._listeners[arg]) {
654
+ VrpcAdapter._listeners[arg] = {
655
+ listener,
656
+ clients: new Set([sender]),
657
+ instances: new Set(),
658
+ event: null
659
+ }
660
+ } else {
661
+ VrpcAdapter._listeners[arg].clients.add(sender)
661
662
  }
662
- if (
663
- (func === 'off' || func === 'removeListener') &&
664
- typeof args[0] === 'string'
665
- ) {
666
- const listener = VrpcAdapter._listeners[sender]
667
- const entry = listener && listener.find(x => x.r === arg)
668
- if (entry) {
669
- const { i, e, f } = entry
670
- VrpcAdapter.getInstance(i).removeListener(e, f)
663
+ // see whether the requested listener is an EventEmitter registration
664
+ if (func === 'on' || func === 'addListener') {
665
+ // if this event is already registered on the given instance
666
+ // avoid a second registration
667
+ if (
668
+ VrpcAdapter._listeners[arg].event &&
669
+ VrpcAdapter._listeners[arg].instances.has(context)
670
+ ) {
671
+ return null // means that this call won't be forwarded
671
672
  }
673
+ VrpcAdapter._listeners[arg].event = args[0]
674
+ VrpcAdapter._listeners[arg].instances.add(context)
675
+ }
676
+ if (func === 'off' || func === 'removeListener') {
677
+ const {
678
+ clients,
679
+ instances,
680
+ listener,
681
+ event
682
+ } = VrpcAdapter._listeners[arg]
683
+ clients.delete(sender)
684
+ instances.delete(context)
685
+ if (clients.size === 0) {
686
+ delete VrpcAdapter._listeners[arg]
687
+ VrpcAdapter.getInstance(context).off(event, listener)
688
+ }
689
+ return null // means that this call won't be forwarded
672
690
  }
673
691
  } else {
674
- // Leave the others untouched
675
- wrapped.push(arg)
692
+ // default behavior is to not touch
693
+ unwrapped.push(arg)
676
694
  }
677
- })
678
- return wrapped
695
+ }
696
+ return unwrapped
697
+ }
698
+
699
+ static _removeAllListeners (event, sender, context) {
700
+ for (const [key, value] of Object.entries(VrpcAdapter._listeners)) {
701
+ if (value.event === event) {
702
+ value.clients.delete(sender)
703
+ if (value.clients.size === 0) {
704
+ delete VrpcAdapter._listeners[key]
705
+ VrpcAdapter.getInstance(context).off(event, value.listener)
706
+ }
707
+ }
708
+ }
709
+ }
710
+
711
+ static _generateCallback (id, sender, instanceId) {
712
+ return (...innerArgs) => {
713
+ // callAll expects the instanceId as first argument
714
+ const a = instanceId ? [instanceId, ...innerArgs] : [...innerArgs]
715
+ VrpcAdapter._callback({ a, s: sender, i: id })
716
+ }
679
717
  }
680
718
 
681
- static _generateWrapper (id, json, instanceId) {
682
- const wrapper = (...innerArgs) => {
683
- // do not even trigger a callback for already offline clients
684
- if (json.s && !VrpcAdapter._listeners[json.s]) return
719
+ static _generateListener (id, sender, instanceId) {
720
+ return (...innerArgs) => {
721
+ // do not even emit for already offline clients
722
+ if (!VrpcAdapter._listeners[id]) return
723
+ // callAll expects the instanceId as first argument
685
724
  const a = instanceId ? [instanceId, ...innerArgs] : [...innerArgs]
686
- VrpcAdapter._callback({ a, s: json.s, f: json.f, i: id })
725
+ VrpcAdapter._callback({ a, s: sender, i: id })
687
726
  }
688
- return wrapper
689
727
  }
690
728
 
691
729
  static _handlePromise (json, promise) {
@@ -812,7 +850,7 @@ class VrpcAdapter {
812
850
  /**
813
851
  * Event 'create'
814
852
  *
815
- * Emitted on creation of named instance
853
+ * Emitted on creation of shared instance
816
854
  *
817
855
  * @event VrpcAdapter#create
818
856
  * @type {Object}
@@ -824,7 +862,7 @@ class VrpcAdapter {
824
862
  /**
825
863
  * Event 'delete'
826
864
  *
827
- * Emitted on deletion of named instance
865
+ * Emitted on deletion of shared instance
828
866
  *
829
867
  * @event VrpcAdapter#delete
830
868
  * @type {Object}