UNPKG

4.51 kBJavaScriptView Raw
1"use strict";
2/* --------------------------------------------------------------------------------------------
3 * Copyright (c) Microsoft Corporation. All rights reserved.
4 * Licensed under the MIT License. See License.txt in the project root for license information.
5 * ------------------------------------------------------------------------------------------ */
6Object.defineProperty(exports, "__esModule", { value: true });
7exports.Emitter = exports.Event = void 0;
8const ral_1 = require("./ral");
9var Event;
10(function (Event) {
11 const _disposable = { dispose() { } };
12 Event.None = function () { return _disposable; };
13})(Event || (exports.Event = Event = {}));
14class CallbackList {
15 add(callback, context = null, bucket) {
16 if (!this._callbacks) {
17 this._callbacks = [];
18 this._contexts = [];
19 }
20 this._callbacks.push(callback);
21 this._contexts.push(context);
22 if (Array.isArray(bucket)) {
23 bucket.push({ dispose: () => this.remove(callback, context) });
24 }
25 }
26 remove(callback, context = null) {
27 if (!this._callbacks) {
28 return;
29 }
30 let foundCallbackWithDifferentContext = false;
31 for (let i = 0, len = this._callbacks.length; i < len; i++) {
32 if (this._callbacks[i] === callback) {
33 if (this._contexts[i] === context) {
34 // callback & context match => remove it
35 this._callbacks.splice(i, 1);
36 this._contexts.splice(i, 1);
37 return;
38 }
39 else {
40 foundCallbackWithDifferentContext = true;
41 }
42 }
43 }
44 if (foundCallbackWithDifferentContext) {
45 throw new Error('When adding a listener with a context, you should remove it with the same context');
46 }
47 }
48 invoke(...args) {
49 if (!this._callbacks) {
50 return [];
51 }
52 const ret = [], callbacks = this._callbacks.slice(0), contexts = this._contexts.slice(0);
53 for (let i = 0, len = callbacks.length; i < len; i++) {
54 try {
55 ret.push(callbacks[i].apply(contexts[i], args));
56 }
57 catch (e) {
58 // eslint-disable-next-line no-console
59 (0, ral_1.default)().console.error(e);
60 }
61 }
62 return ret;
63 }
64 isEmpty() {
65 return !this._callbacks || this._callbacks.length === 0;
66 }
67 dispose() {
68 this._callbacks = undefined;
69 this._contexts = undefined;
70 }
71}
72class Emitter {
73 constructor(_options) {
74 this._options = _options;
75 }
76 /**
77 * For the public to allow to subscribe
78 * to events from this Emitter
79 */
80 get event() {
81 if (!this._event) {
82 this._event = (listener, thisArgs, disposables) => {
83 if (!this._callbacks) {
84 this._callbacks = new CallbackList();
85 }
86 if (this._options && this._options.onFirstListenerAdd && this._callbacks.isEmpty()) {
87 this._options.onFirstListenerAdd(this);
88 }
89 this._callbacks.add(listener, thisArgs);
90 const result = {
91 dispose: () => {
92 if (!this._callbacks) {
93 // disposable is disposed after emitter is disposed.
94 return;
95 }
96 this._callbacks.remove(listener, thisArgs);
97 result.dispose = Emitter._noop;
98 if (this._options && this._options.onLastListenerRemove && this._callbacks.isEmpty()) {
99 this._options.onLastListenerRemove(this);
100 }
101 }
102 };
103 if (Array.isArray(disposables)) {
104 disposables.push(result);
105 }
106 return result;
107 };
108 }
109 return this._event;
110 }
111 /**
112 * To be kept private to fire an event to
113 * subscribers
114 */
115 fire(event) {
116 if (this._callbacks) {
117 this._callbacks.invoke.call(this._callbacks, event);
118 }
119 }
120 dispose() {
121 if (this._callbacks) {
122 this._callbacks.dispose();
123 this._callbacks = undefined;
124 }
125 }
126}
127exports.Emitter = Emitter;
128Emitter._noop = function () { };