@nxtedition/deepstream.io-client-js 23.4.45 → 23.4.46

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": "@nxtedition/deepstream.io-client-js",
3
- "version": "23.4.45",
3
+ "version": "23.4.46",
4
4
  "description": "the javascript client for deepstream.io",
5
5
  "homepage": "http://deepstream.io",
6
6
  "bugs": {
@@ -58,7 +58,7 @@ class RecordHandler {
58
58
  invariant(rec.refs === 0, 'cannot prune referenced record')
59
59
  invariant(!this._pending.has(rec), 'cannot prune pending record')
60
60
 
61
- rec._unsubscribe()
61
+ rec._$dispose()
62
62
  this._records.delete(rec.name)
63
63
  this._stats.destroyed++
64
64
  }
@@ -76,25 +76,27 @@ class RecordHandler {
76
76
  _prune()
77
77
  }
78
78
 
79
- _onRef(rec) {
80
- if (rec.refs === 0 && !this._pending.has(rec)) {
79
+ _onRef(rec, prevRefs) {
80
+ const curr = rec.refs === 0
81
+ const prev = prevRefs === 0
82
+
83
+ if (curr && !prev) {
81
84
  this._pruning.add(rec)
82
- } else if (rec.refs === 1) {
85
+ } else if (!curr && prev) {
83
86
  this._pruning.delete(rec)
84
87
  }
85
88
  }
86
89
 
87
- _onPending(rec) {
88
- if (rec.state > C.RECORD_STATE.PENDING) {
89
- this._pending.delete(rec)
90
- if (rec.refs === 0) {
91
- this._pruning.add(rec)
92
- }
93
- } else {
90
+ _onState(rec, prevState) {
91
+ const curr = rec.state < C.RECORD_STATE.SERVER
92
+ const prev = prevState < C.RECORD_STATE.SERVER
93
+
94
+ if (curr && !prev) {
94
95
  this._pending.add(rec)
95
- if (rec.refs === 0) {
96
- this._pruning.delete(rec)
97
- }
96
+ rec.ref()
97
+ } else if (!curr && prev) {
98
+ this._pending.delete(rec)
99
+ rec.unref()
98
100
  }
99
101
  }
100
102
 
@@ -23,9 +23,7 @@ class Record {
23
23
  this._updating = null
24
24
  this._patches = null
25
25
 
26
- this._handler._onPending(this)
27
-
28
- this._subscribe()
26
+ this._mutate(() => this._subscribe())
29
27
  }
30
28
 
31
29
  get name() {
@@ -49,12 +47,14 @@ class Record {
49
47
  }
50
48
 
51
49
  ref() {
50
+ const prevRefs = this._refs
51
+
52
52
  this._refs += 1
53
53
  if (this._refs === 1) {
54
- this._subscribe()
54
+ this._mutate(() => this._subscribe())
55
55
  }
56
56
 
57
- this._handler._onRef(this)
57
+ this._handler._onRef(this, prevRefs)
58
58
 
59
59
  return this
60
60
  }
@@ -62,9 +62,11 @@ class Record {
62
62
  unref() {
63
63
  invariant(this._refs > 0, this._name + ' missing refs')
64
64
 
65
+ const prevRefs = this._refs
66
+
65
67
  this._refs -= 1
66
68
 
67
- this._handler._onRef(this)
69
+ this._handler._onRef(this, prevRefs)
68
70
 
69
71
  return this
70
72
  }
@@ -99,39 +101,39 @@ class Record {
99
101
  }
100
102
 
101
103
  set(pathOrData, dataOrNil) {
102
- invariant(this._refs > 0, this._name + ' missing refs')
104
+ return this._mutate(() => {
105
+ invariant(this._refs > 0, this._name + ' missing refs')
103
106
 
104
- if (this._version.charAt(0) === 'I' || this._name.startsWith('_')) {
105
- this._error(C.EVENT.USER_ERROR, 'cannot set')
106
- return
107
- }
107
+ if (this._version.charAt(0) === 'I' || this._name.startsWith('_')) {
108
+ this._error(C.EVENT.USER_ERROR, 'cannot set')
109
+ return
110
+ }
108
111
 
109
- const path = arguments.length === 1 ? undefined : pathOrData
110
- const data = arguments.length === 1 ? pathOrData : dataOrNil
112
+ const path = arguments.length === 1 ? undefined : pathOrData
113
+ const data = arguments.length === 1 ? pathOrData : dataOrNil
111
114
 
112
- if (path === undefined && !utils.isPlainObject(data)) {
113
- throw new Error('invalid argument: data')
114
- }
115
- if (path === undefined && Object.keys(data).some((prop) => prop.startsWith('_'))) {
116
- throw new Error('invalid argument: data')
117
- }
118
- if (
119
- path !== undefined &&
120
- (typeof path !== 'string' || path.length === 0 || path.startsWith('_')) &&
121
- (!Array.isArray(path) || path.length === 0 || path[0].startsWith('_'))
122
- ) {
123
- throw new Error('invalid argument: path')
124
- }
115
+ if (path === undefined && !utils.isPlainObject(data)) {
116
+ throw new Error('invalid argument: data')
117
+ }
118
+ if (path === undefined && Object.keys(data).some((prop) => prop.startsWith('_'))) {
119
+ throw new Error('invalid argument: data')
120
+ }
121
+ if (
122
+ path !== undefined &&
123
+ (typeof path !== 'string' || path.length === 0 || path.startsWith('_')) &&
124
+ (!Array.isArray(path) || path.length === 0 || path[0].startsWith('_'))
125
+ ) {
126
+ throw new Error('invalid argument: path')
127
+ }
125
128
 
126
- if (this._state < Record.STATE.SERVER) {
127
- this._patches = path && this._patches ? this._patches : []
128
- this._patches.push(path, cloneDeep(data))
129
- this._state = Record.STATE.PENDING
130
- }
129
+ if (this._state < Record.STATE.SERVER) {
130
+ this._patches = path && this._patches ? this._patches : []
131
+ this._patches.push(path, cloneDeep(data))
132
+ this._state = Record.STATE.PENDING
133
+ }
131
134
 
132
- if (this._update(jsonPath.set(this._data, path, data, false))) {
133
- this._emitUpdate()
134
- }
135
+ this._update(jsonPath.set(this._data, path, data, false))
136
+ })
135
137
  }
136
138
 
137
139
  // TODO (fix): timeout + signal
@@ -205,22 +207,11 @@ class Record {
205
207
  })
206
208
  }
207
209
 
208
- _emitUpdate() {
209
- try {
210
- this._subscriptionsEmitting = true
211
- for (const fn of this._subscriptions) {
212
- fn(this)
213
- }
214
- } finally {
215
- this._subscriptionsEmitting = false
216
- }
217
- }
218
-
219
210
  _$onMessage(message) {
220
211
  if (message.action === C.ACTIONS.UPDATE) {
221
- this._onUpdate(message.data)
212
+ this._mutate(() => this._onUpdate(message.data))
222
213
  } else if (message.action === C.ACTIONS.SUBSCRIPTION_HAS_PROVIDER) {
223
- this._onSubscriptionHasProvider(message.data)
214
+ this._mutate(() => this._onSubscriptionHasProvider(message.data))
224
215
  } else {
225
216
  return false
226
217
  }
@@ -229,25 +220,29 @@ class Record {
229
220
  }
230
221
 
231
222
  _$onConnectionStateChange() {
232
- const connection = this._handler._connection
233
- if (connection.connected) {
234
- if (this._refs > 0) {
235
- this._subscribe()
236
- }
223
+ return this._mutate(() => {
224
+ const connection = this._handler._connection
225
+ if (connection.connected) {
226
+ if (this._refs > 0) {
227
+ this._subscribe()
228
+ }
237
229
 
238
- if (this._updating) {
239
- for (const update of this._updating.values()) {
240
- connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.UPDATE, update)
230
+ if (this._updating) {
231
+ for (const update of this._updating.values()) {
232
+ connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.UPDATE, update)
233
+ }
234
+ }
235
+ } else {
236
+ this._subscribed = false
237
+ if (this._state > Record.STATE.CLIENT) {
238
+ this._state = Record.STATE.CLIENT
241
239
  }
242
240
  }
243
- } else {
244
- this._subscribed = false
245
- if (this._state > Record.STATE.CLIENT) {
246
- this._state = Record.STATE.CLIENT
247
- this._handler._onPending(this)
248
- this._emitUpdate()
249
- }
250
- }
241
+ })
242
+ }
243
+
244
+ _$dispose() {
245
+ this._mutate(() => this._unsubscribe())
251
246
  }
252
247
 
253
248
  _subscribe() {
@@ -272,8 +267,6 @@ class Record {
272
267
  this._subscribed = false
273
268
  if (this._state > Record.STATE.CLIENT) {
274
269
  this._state = Record.STATE.CLIENT
275
- this._handler._onPending(this)
276
- this._emitUpdate()
277
270
  }
278
271
  }
279
272
 
@@ -304,9 +297,6 @@ class Record {
304
297
  }
305
298
 
306
299
  _onUpdate([, version, data]) {
307
- const prevData = this._data
308
- const prevVersion = this._version
309
-
310
300
  if (this._updating?.delete(version)) {
311
301
  this._handler._stats.updating -= 1
312
302
  }
@@ -334,29 +324,18 @@ class Record {
334
324
 
335
325
  if (this._state < Record.STATE.SERVER) {
336
326
  this._state = this._version.charAt(0) === 'I' ? Record.STATE.STALE : Record.STATE.SERVER
337
- this._handler._onPending(this)
338
- this._emitUpdate()
339
- } else if (this._data !== prevData || this._version !== prevVersion) {
340
- this._emitUpdate()
341
327
  }
342
328
  }
343
329
 
344
330
  _onSubscriptionHasProvider([, hasProvider]) {
345
- if (this._state < Record.STATE.SERVER) {
346
- return
347
- }
348
-
349
- const provided = hasProvider && messageParser.convertTyped(hasProvider, this._handler._client)
350
- const state = provided
351
- ? Record.STATE.PROVIDER
352
- : this._version.charAt(0) === 'I'
353
- ? Record.STATE.STALE
354
- : Record.STATE.SERVER
355
-
356
- if (this._state !== state) {
357
- this._state = state
358
- this._emitUpdate()
359
- }
331
+ this._state =
332
+ hasProvider &&
333
+ messageParser.convertTyped(hasProvider, this._handler._client) &&
334
+ this._state >= Record.STATE.SERVER
335
+ ? Record.STATE.PROVIDER
336
+ : this._version.charAt(0) === 'I'
337
+ ? Record.STATE.STALE
338
+ : Record.STATE.SERVER
360
339
  }
361
340
 
362
341
  _error(event, msgOrError, data) {
@@ -376,6 +355,32 @@ class Record {
376
355
  }
377
356
  return `${start}-${revid}`
378
357
  }
358
+
359
+ _mutate(fn) {
360
+ const prevState = this._state
361
+ const prevData = this._data
362
+ const prevVersion = this._version
363
+
364
+ const ret = fn()
365
+
366
+ if (this._state !== prevState || this._data !== prevData || this._version !== prevVersion) {
367
+ try {
368
+ this._subscriptionsEmitting = true
369
+
370
+ if (this._state !== prevState) {
371
+ this._handler.onState(this, prevState)
372
+ }
373
+
374
+ for (const fn of this._subscriptions) {
375
+ fn(this)
376
+ }
377
+ } finally {
378
+ this._subscriptionsEmitting = false
379
+ }
380
+ }
381
+
382
+ return ret
383
+ }
379
384
  }
380
385
 
381
386
  // Compat