@irrelon/emitter 5.0.5 → 6.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/src/Emitter.ts CHANGED
@@ -25,12 +25,24 @@
25
25
  Source: https://github.com/irrelon/emitter
26
26
 
27
27
  Changelog:
28
+ Version 6.0.0: Updated to allow event listeners to return data to
29
+ the caller of the emit() function, e.g.
30
+ `const results = emitter.emit("myEventName");`
31
+
32
+ The results are an array of all return values from any listener
33
+ functions that were called by the event "myEventName". This is
34
+ useful if you want event listeners to act as data providers for
35
+ particular events.
36
+
37
+ Listeners that return `ListenerReturnFlag.cancel` will cancel
38
+ the event call to any further listeners for that one event
39
+ emit.
28
40
  Version 5.0.3 and 5.0.4: Updated to allow specifying an events type
29
41
  to the Emitter to allow complete type safety when registering
30
42
  listeners and emitting events.
31
43
 
32
44
  Updated the build and package to split between delivery of CJS
33
- and MJS module types so that this package can be eiter imported
45
+ and ESM module types so that this package can be eiter imported
34
46
  or required without having to jump through any hoops.
35
47
  Version 5.0.2:
36
48
  Removed some unnecessary code, updated to be in step with version
@@ -94,34 +106,40 @@
94
106
  export type AnyFunction<ReturnType = any> = (...args: any[]) => ReturnType;
95
107
  export type AnyConstructor = new (...args: any[]) => any;
96
108
 
97
- export enum EventReturnFlag {
98
- none,
99
- cancel
109
+ export enum ListenerReturnFlag {
110
+ none = "!+_NONE",
111
+ cancel = "!+_CANCEL"
100
112
  }
101
113
 
102
- export type EventListenerCallback<EventCallbackFunctionSignature extends AnyFunction = AnyFunction> = (...args: Parameters<EventCallbackFunctionSignature>) => ReturnType<EventCallbackFunctionSignature>;
114
+ export type EventListenerCallback<EventCallbackFunctionSignature extends AnyFunction = AnyFunction> = (
115
+ ...args: Parameters<EventCallbackFunctionSignature>
116
+ ) => ReturnType<EventCallbackFunctionSignature>;
103
117
 
104
118
  export interface EventStaticEmitterObject<EventCallbackFunctionSignature extends AnyFunction = AnyFunction> {
105
119
  id: string;
106
120
  args: Parameters<EventCallbackFunctionSignature>;
107
121
  }
108
122
 
109
- export interface EmitterEventsInterface {
110
- [key: string]: AnyFunction
123
+ export interface EmitterAnyEventsInterface {
124
+ [key: string]: AnyFunction;
111
125
  }
112
126
 
113
- export type ConvertInterfaceToDict<T> = {
127
+ export type EmitterEventsInterface<T> = {
114
128
  [K in keyof T]: T[K];
115
129
  };
116
130
 
117
131
  /**
118
132
  * Creates a new class with the capability to emit events.
119
133
  */
120
- export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEventsInterface> {
134
+ export class Emitter<EventsInterface extends EmitterEventsInterface<EventsInterface> = EmitterAnyEventsInterface> {
121
135
  _eventsEmitting: boolean = false;
122
136
  _eventRemovalQueue: any[] = [];
123
- _eventListeners?: { [EventName in (keyof EventsInterface)]?: Record<string, EventListenerCallback<EventsInterface[EventName]>[]> } = {};
124
- _eventStaticEmitters: {[EventName in (keyof EventsInterface)]?: EventStaticEmitterObject<EventsInterface[EventName]>[] } = {};
137
+ _eventListeners?: {
138
+ [EventName in keyof EventsInterface]?: Record<string, EventListenerCallback<EventsInterface[EventName]>[]>;
139
+ } = {};
140
+ _eventStaticEmitters: {
141
+ [EventName in keyof EventsInterface]?: EventStaticEmitterObject<EventsInterface[EventName]>[];
142
+ } = {};
125
143
  _eventsAllowDefer: boolean = false;
126
144
  _eventsDeferTimeouts: Record<any, number> = {};
127
145
 
@@ -133,7 +151,11 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
133
151
  * @param listener The method to call when the event is fired.
134
152
  * @returns The emitter instance.
135
153
  */
136
- _on<EventName extends keyof EventsInterface> (eventName: EventName, id: string, listener: EventListenerCallback<EventsInterface[EventName]>) {
154
+ _on<EventName extends keyof EventsInterface> (
155
+ eventName: EventName,
156
+ id: string,
157
+ listener: EventListenerCallback<EventsInterface[EventName]>
158
+ ) {
137
159
  const generateTimeout = (emitter: EventStaticEmitterObject<EventsInterface[EventName]>) => {
138
160
  setTimeout(() => {
139
161
  listener(...emitter.args);
@@ -141,12 +163,17 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
141
163
  };
142
164
 
143
165
  this._eventListeners = this._eventListeners || {};
144
- const nonNullableEventListeners = this._eventListeners[eventName] = this._eventListeners[eventName] || {};
166
+ const nonNullableEventListeners = (this._eventListeners[eventName] = this._eventListeners[eventName] || {});
145
167
  nonNullableEventListeners[id] = nonNullableEventListeners[id] || [];
146
168
  nonNullableEventListeners[id].push(listener);
147
169
 
148
170
  // Check for any static emitters, and fire the event if any exist
149
- if (!this._eventStaticEmitters || !this._eventStaticEmitters[eventName] || !this._eventStaticEmitters[eventName]!.length) return this;
171
+ if (
172
+ !this._eventStaticEmitters ||
173
+ !this._eventStaticEmitters[eventName] ||
174
+ !this._eventStaticEmitters[eventName]!.length
175
+ )
176
+ return this;
150
177
 
151
178
  // Emit events for each emitter
152
179
  for (let i = 0; i < this._eventStaticEmitters[eventName]!.length; i++) {
@@ -171,11 +198,17 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
171
198
  * @param listener The method to call when the event is fired.
172
199
  * @returns The emitter instance.
173
200
  */
174
- _once<EventName extends keyof EventsInterface> (eventName: EventName, id: string, listener: EventListenerCallback<EventsInterface[EventName]>) {
201
+ _once<EventName extends keyof EventsInterface> (
202
+ eventName: EventName,
203
+ id: string,
204
+ listener: EventListenerCallback<EventsInterface[EventName]>
205
+ ) {
175
206
  let fired = false;
176
207
  let originalReturnData: ReturnType<EventsInterface[EventName]>;
177
208
 
178
- const internalCallback: EventListenerCallback<EventsInterface[EventName]> = (...args: Parameters<EventsInterface[EventName]>): ReturnType<EventsInterface[EventName]> => {
209
+ const internalCallback: EventListenerCallback<EventsInterface[EventName]> = (
210
+ ...args: Parameters<EventsInterface[EventName]>
211
+ ): ReturnType<EventsInterface[EventName]> => {
179
212
  if (fired) return originalReturnData;
180
213
 
181
214
  fired = true;
@@ -196,9 +229,14 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
196
229
  * or once() call to cancel.
197
230
  * @returns The emitter instance.
198
231
  */
199
- _off<EventName extends keyof EventsInterface> (eventName: EventName, id: string, listener?: EventListenerCallback<EventsInterface[EventName]>): this {
232
+ _off<EventName extends keyof EventsInterface> (
233
+ eventName: EventName,
234
+ id: string,
235
+ listener?: EventListenerCallback<EventsInterface[EventName]>
236
+ ): this {
200
237
  // If the event name doesn't have any listeners, exit early
201
- if (!this._eventListeners || !this._eventListeners[eventName] || !this._eventListeners[eventName]![id]) return this;
238
+ if (!this._eventListeners || !this._eventListeners[eventName] || !this._eventListeners[eventName]![id])
239
+ return this;
202
240
 
203
241
  // If we are emitting events at the moment, don't remove this listener
204
242
  // until the process has completed, so we queue for removal instead
@@ -244,9 +282,20 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
244
282
  * @param listener The method to call when the event is fired.
245
283
  * @returns The emitter instance.
246
284
  */
247
- on<EventName extends keyof EventsInterface> (eventName: EventName, id: string, listener: EventListenerCallback<EventsInterface[EventName]>): this;
248
- on<EventName extends keyof EventsInterface> (eventName: EventName, listener: EventListenerCallback<EventsInterface[EventName]>): this;
249
- on<EventName extends keyof EventsInterface> (eventName: EventName, idOrListener: string | EventListenerCallback<EventsInterface[EventName]>, listener?: EventListenerCallback<EventsInterface[EventName]>): this {
285
+ on<EventName extends keyof EventsInterface>(
286
+ eventName: EventName,
287
+ id: string,
288
+ listener: EventListenerCallback<EventsInterface[EventName]>
289
+ ): this;
290
+ on<EventName extends keyof EventsInterface>(
291
+ eventName: EventName,
292
+ listener: EventListenerCallback<EventsInterface[EventName]>
293
+ ): this;
294
+ on<EventName extends keyof EventsInterface> (
295
+ eventName: EventName,
296
+ idOrListener: string | EventListenerCallback<EventsInterface[EventName]>,
297
+ listener?: EventListenerCallback<EventsInterface[EventName]>
298
+ ): this {
250
299
  if (typeof idOrListener === "string") {
251
300
  return this._on(eventName, idOrListener, listener as EventListenerCallback<EventsInterface[EventName]>);
252
301
  }
@@ -262,8 +311,15 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
262
311
  * @param listener
263
312
  * @returns The emitter instance.
264
313
  */
265
- once<EventName extends keyof EventsInterface> (eventName: EventName, id: string, listener: EventListenerCallback<EventsInterface[EventName]>): this;
266
- once<EventName extends keyof EventsInterface> (eventName: EventName, listener: EventListenerCallback<EventsInterface[EventName]>): this;
314
+ once<EventName extends keyof EventsInterface>(
315
+ eventName: EventName,
316
+ id: string,
317
+ listener: EventListenerCallback<EventsInterface[EventName]>
318
+ ): this;
319
+ once<EventName extends keyof EventsInterface>(
320
+ eventName: EventName,
321
+ listener: EventListenerCallback<EventsInterface[EventName]>
322
+ ): this;
267
323
  once<EventName extends keyof EventsInterface> (eventName: EventName, ...rest: any[]): this {
268
324
  const restTypes = rest.map((arg) => typeof arg);
269
325
 
@@ -286,8 +342,15 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
286
342
  * @param listener The method to call when the event is fired.
287
343
  * @returns The emitter instance.
288
344
  */
289
- overwrite<EventName extends keyof EventsInterface> (eventName: EventName, id: string, listener: EventListenerCallback<EventsInterface[EventName]>): this;
290
- overwrite<EventName extends keyof EventsInterface> (eventName: EventName, listener: EventListenerCallback<EventsInterface[EventName]>): this;
345
+ overwrite<EventName extends keyof EventsInterface>(
346
+ eventName: EventName,
347
+ id: string,
348
+ listener: EventListenerCallback<EventsInterface[EventName]>
349
+ ): this;
350
+ overwrite<EventName extends keyof EventsInterface>(
351
+ eventName: EventName,
352
+ listener: EventListenerCallback<EventsInterface[EventName]>
353
+ ): this;
291
354
  overwrite<EventName extends keyof EventsInterface> (eventName: EventName, ...rest: any[]) {
292
355
  const restTypes = rest.map((arg) => typeof arg);
293
356
 
@@ -308,9 +371,16 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
308
371
  * or once() call to cancel.
309
372
  * @returns The emitter instance.
310
373
  */
311
- off<EventName extends keyof EventsInterface> (eventName: EventName, id: string, listener?: EventListenerCallback<EventsInterface[EventName]>): this;
312
- off<EventName extends keyof EventsInterface> (eventName: EventName, listener?: EventListenerCallback<EventsInterface[EventName]>): this;
313
- off<EventName extends keyof EventsInterface> (eventName: EventName): this;
374
+ off<EventName extends keyof EventsInterface>(
375
+ eventName: EventName,
376
+ id: string,
377
+ listener?: EventListenerCallback<EventsInterface[EventName]>
378
+ ): this;
379
+ off<EventName extends keyof EventsInterface>(
380
+ eventName: EventName,
381
+ listener?: EventListenerCallback<EventsInterface[EventName]>
382
+ ): this;
383
+ off<EventName extends keyof EventsInterface>(eventName: EventName): this;
314
384
  off<EventName extends keyof EventsInterface> (eventName: EventName, ...rest: any[]) {
315
385
  if (rest.length === 0) {
316
386
  // Only event was provided, use * as the id to mean "any without"
@@ -330,6 +400,33 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
330
400
  return this._off(eventName, rest[0], rest[1]);
331
401
  }
332
402
 
403
+ _emitToArrayOfListeners<EventName extends keyof EventsInterface> (
404
+ arr: EventListenerCallback<EventsInterface[EventName]>[],
405
+ data: Parameters<EventsInterface[EventName]>
406
+ ): (ReturnType<EventsInterface[EventName]> | ListenerReturnFlag)[] {
407
+ const arrCount = arr.length;
408
+ const resultArr: (ReturnType<EventsInterface[EventName]> | ListenerReturnFlag)[] = [];
409
+
410
+ for (let arrIndex = 0; arrIndex < arrCount; arrIndex++) {
411
+ // Check we have a function to execute
412
+ const tmpFunc = arr[arrIndex];
413
+
414
+ if (typeof tmpFunc !== "function") {
415
+ continue;
416
+ }
417
+
418
+ const eventListenerResponse = tmpFunc(...data);
419
+ resultArr.push(eventListenerResponse);
420
+
421
+ if (eventListenerResponse === ListenerReturnFlag.cancel) {
422
+ // Cancel further event processing
423
+ break;
424
+ }
425
+ }
426
+
427
+ return resultArr;
428
+ }
429
+
333
430
  /**
334
431
  * Emit an event by name.
335
432
  * @param eventName The name of the event to emit.
@@ -359,87 +456,41 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
359
456
  * // The console output is:
360
457
  * // data1, data2
361
458
  */
362
- async emit<EventName extends keyof EventsInterface> (eventName: EventName, ...data: Parameters<EventsInterface[EventName]>): Promise<EventReturnFlag> {
363
- if (!this._eventListeners) {
364
- return EventReturnFlag.none;
365
- }
366
-
367
- const id = "*";
368
-
369
- let returnFlag: EventReturnFlag = EventReturnFlag.none;
370
- this._eventsEmitting = true;
371
-
372
- if (this._eventListeners[eventName] && this._eventListeners[eventName]![id]) {
373
- // Handle global emit
374
- const arr = this._eventListeners[eventName]![id];
375
-
376
- const promiseArr = arr.map((tmpFunc) => {
377
- if (typeof tmpFunc !== "function") return;
378
- return tmpFunc(...data);
379
- });
380
-
381
- const result = (await Promise.all(promiseArr)).find((tmpResult) => tmpResult !== EventReturnFlag.none);
382
-
383
- if (result) {
384
- returnFlag = EventReturnFlag.cancel;
385
- }
386
- }
387
-
388
- this._eventsEmitting = false;
389
- this._processRemovalQueue();
390
-
391
- return returnFlag;
459
+ emit<EventName extends keyof EventsInterface> (
460
+ eventName: EventName,
461
+ ...data: Parameters<EventsInterface[EventName]>
462
+ ): (ReturnType<EventsInterface[EventName]> | ListenerReturnFlag)[] {
463
+ return this.emitId<EventName>(eventName, "*", ...data);
392
464
  }
393
465
 
394
- emitId<EventName extends keyof EventsInterface> (eventName: EventName, id: string, ...data: Parameters<EventsInterface[EventName]>): EventReturnFlag {
395
- if (!this._eventListeners) {
396
- return EventReturnFlag.none;
466
+ emitId<EventName extends keyof EventsInterface> (
467
+ eventName: EventName,
468
+ id: string,
469
+ ...data: Parameters<EventsInterface[EventName]>
470
+ ): (ReturnType<EventsInterface[EventName]> | ListenerReturnFlag)[] {
471
+ if (!this._eventListeners || !this._eventListeners[eventName]) {
472
+ return [];
397
473
  }
398
474
 
399
- this._eventListeners = this._eventListeners || {};
475
+ let emitterResult: (ReturnType<EventsInterface[EventName]> | ListenerReturnFlag)[] = [];
400
476
  this._eventsEmitting = true;
401
477
 
402
- if (!this._eventListeners[eventName]) {
403
- this._eventsEmitting = false;
404
- this._processRemovalQueue();
405
-
406
- return EventReturnFlag.none;
407
- }
408
-
409
478
  // Handle id emit
410
479
  if (this._eventListeners[eventName]![id]) {
411
480
  const arr = this._eventListeners[eventName]![id];
412
- const arrCount = arr.length;
413
-
414
- for (let arrIndex = 0; arrIndex < arrCount; arrIndex++) {
415
- // Check we have a function to execute
416
- const tmpFunc = arr[arrIndex];
417
-
418
- if (typeof tmpFunc === "function") {
419
- tmpFunc.call(this, ...data);
420
- }
421
- }
481
+ emitterResult = emitterResult.concat(this._emitToArrayOfListeners<EventName>(arr, data));
422
482
  }
423
483
 
424
- // Handle global emit
425
- if (this._eventListeners[eventName]!["*"]) {
484
+ // Handle global emit if the id passed wasn't already a global (*) id
485
+ if (id !== "*" && this._eventListeners[eventName]!["*"]) {
426
486
  const arr = this._eventListeners[eventName]!["*"];
427
- const arrCount = arr.length;
428
-
429
- for (let arrIndex = 0; arrIndex < arrCount; arrIndex++) {
430
- // Check we have a function to execute
431
- const tmpFunc = arr[arrIndex];
432
-
433
- if (typeof tmpFunc === "function") {
434
- tmpFunc.call(this, ...data);
435
- }
436
- }
487
+ emitterResult = emitterResult.concat(this._emitToArrayOfListeners<EventName>(arr, data));
437
488
  }
438
489
 
439
490
  this._eventsEmitting = false;
440
491
  this._processRemovalQueue();
441
492
 
442
- return EventReturnFlag.none;
493
+ return emitterResult;
443
494
  }
444
495
 
445
496
  /**
@@ -451,7 +502,10 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
451
502
  * @returns The emitter instance.
452
503
  * @private
453
504
  */
454
- emitStatic<EventName extends keyof EventsInterface> (eventName: EventName, ...data: Parameters<EventsInterface[EventName]>) {
505
+ emitStatic<EventName extends keyof EventsInterface> (
506
+ eventName: EventName,
507
+ ...data: Parameters<EventsInterface[EventName]>
508
+ ) {
455
509
  const id = "*";
456
510
  this._eventListeners = this._eventListeners || {};
457
511
  this._eventsEmitting = true;
@@ -476,8 +530,8 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
476
530
  this._eventStaticEmitters = this._eventStaticEmitters || {};
477
531
  this._eventStaticEmitters[eventName] = this._eventStaticEmitters[eventName] || [];
478
532
  this._eventStaticEmitters[eventName]!.push({
479
- "id": "*",
480
- "args": data
533
+ id: "*",
534
+ args: data
481
535
  });
482
536
 
483
537
  this._processRemovalQueue();
@@ -495,7 +549,11 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
495
549
  * @returns The emitter instance.
496
550
  * @private
497
551
  */
498
- emitStaticId<EventName extends keyof EventsInterface> (eventName: EventName, id: string, ...data: Parameters<EventsInterface[EventName]>) {
552
+ emitStaticId<EventName extends keyof EventsInterface> (
553
+ eventName: EventName,
554
+ id: string,
555
+ ...data: Parameters<EventsInterface[EventName]>
556
+ ) {
499
557
  if (!id) throw new Error("Missing id from emitId call!");
500
558
 
501
559
  this._eventListeners = this._eventListeners || {};
@@ -539,7 +597,7 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
539
597
  this._eventStaticEmitters[eventName] = this._eventStaticEmitters[eventName] || [];
540
598
  this._eventStaticEmitters[eventName]!.push({
541
599
  id,
542
- "args": data
600
+ args: data
543
601
  });
544
602
 
545
603
  this._processRemovalQueue();
@@ -643,7 +701,10 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
643
701
  * @param {...any} data Optional arguments to emit with the event.
644
702
  * @returns The emitter instance.
645
703
  */
646
- deferEmit<EventName extends keyof EventsInterface> (eventName: EventName, ...data: Parameters<EventsInterface[EventName]>) {
704
+ deferEmit<EventName extends keyof EventsInterface> (
705
+ eventName: EventName,
706
+ ...data: Parameters<EventsInterface[EventName]>
707
+ ) {
647
708
  if (!this._eventsAllowDefer) {
648
709
  // Check for an existing timeout
649
710
  this._eventsDeferTimeouts = this._eventsDeferTimeouts || {};
@@ -663,13 +724,22 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
663
724
  return this;
664
725
  }
665
726
 
727
+ /**
728
+ * Returns true if the result from an emit() call passed as the first
729
+ * argument contains a cancellation flag.
730
+ * @param resultArr
731
+ */
732
+ didCancel (resultArr: (unknown | ListenerReturnFlag)[]) {
733
+ return resultArr.findIndex((result) => result === ListenerReturnFlag.cancel) > -1;
734
+ }
735
+
666
736
  /**
667
737
  * If events are cleared with the off() method while the event emitter is
668
738
  * actively processing any events then the off() calls get added to a
669
739
  * queue to be executed after the event emitter is finished. This stops
670
- * errors that might occur by potentially modifying the event queue while
671
- * the emitter is running through them. This method is called after the
672
- * event emitter is finished processing.
740
+ * errors that might occur by potentially mutating the event listener array
741
+ * while the emitter is running through them. This method is called after
742
+ * the event emitter is finished processing.
673
743
  * @private
674
744
  */
675
745
  _processRemovalQueue () {
@@ -687,9 +757,9 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
687
757
  }
688
758
  }
689
759
 
690
- export function makeEmitter (obj: AnyConstructor, prototypeMode: boolean): Emitter;
691
- export function makeEmitter (obj: boolean): Emitter;
692
- export function makeEmitter (obj: Record<string, unknown>, prototypeMode: boolean): Emitter;
760
+ export function makeEmitter(obj: AnyConstructor, prototypeMode: boolean): Emitter;
761
+ export function makeEmitter(obj: boolean): Emitter;
762
+ export function makeEmitter(obj: Record<string, unknown>, prototypeMode: boolean): Emitter;
693
763
  export function makeEmitter (obj: any, prototypeMode?: any) {
694
764
  let operateOnObject;
695
765
 
@@ -713,7 +783,9 @@ export function makeEmitter (obj: any, prototypeMode?: any) {
713
783
 
714
784
  if (prototypeMode) {
715
785
  if (obj.prototype === undefined) {
716
- throw new Error("Cannot modify prototype of passed object, it has no prototype property! Was it instantiated with the new operator correctly?");
786
+ throw new Error(
787
+ "Cannot modify prototype of passed object, it has no prototype property! Was it instantiated with the new operator correctly?"
788
+ );
717
789
  }
718
790
 
719
791
  operateOnObject = obj.prototype;
@@ -736,4 +808,4 @@ export function makeEmitter (obj: any, prototypeMode?: any) {
736
808
  operateOnObject._processRemovalQueue = Emitter.prototype._processRemovalQueue;
737
809
 
738
810
  return obj;
739
- }
811
+ }