Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/third_party/closure/goog/disposable/disposable.js
4209 views
1
/**
2
* @license
3
* Copyright The Closure Library Authors.
4
* SPDX-License-Identifier: Apache-2.0
5
*/
6
7
/**
8
* @fileoverview Implements the disposable interface.
9
*/
10
11
goog.provide('goog.Disposable');
12
13
goog.require('goog.disposable.IDisposable');
14
goog.require('goog.dispose');
15
/**
16
* TODO(user): Remove this require.
17
* @suppress {extraRequire}
18
*/
19
goog.require('goog.disposeAll');
20
21
goog.require('goog.utils');
22
23
/**
24
* Class that provides the basic implementation for disposable objects. If your
25
* class holds references or resources that can't be collected by standard GC,
26
* it should extend this class or implement the disposable interface (defined
27
* in goog.disposable.IDisposable). See description of
28
* goog.disposable.IDisposable for examples of cleanup.
29
* @constructor
30
* @implements {goog.disposable.IDisposable}
31
*/
32
goog.Disposable = function() {
33
'use strict';
34
/**
35
* If monitoring the goog.Disposable instances is enabled, stores the creation
36
* stack trace of the Disposable instance.
37
* @type {string|undefined}
38
*/
39
this.creationStack;
40
41
if (goog.Disposable.MONITORING_MODE != goog.Disposable.MonitoringMode.OFF) {
42
if (goog.Disposable.INCLUDE_STACK_ON_CREATION) {
43
this.creationStack = new Error().stack;
44
}
45
goog.Disposable.instances_[goog.utils.getUid(this)] = this;
46
}
47
// Support sealing
48
this.disposed_ = this.disposed_;
49
this.onDisposeCallbacks_ = this.onDisposeCallbacks_;
50
};
51
52
53
/**
54
* @enum {number} Different monitoring modes for Disposable.
55
*/
56
goog.Disposable.MonitoringMode = {
57
/**
58
* No monitoring.
59
*/
60
OFF: 0,
61
/**
62
* Creating and disposing the goog.Disposable instances is monitored. All
63
* disposable objects need to call the `goog.Disposable` base
64
* constructor. The PERMANENT mode must be switched on before creating any
65
* goog.Disposable instances.
66
*/
67
PERMANENT: 1,
68
/**
69
* INTERACTIVE mode can be switched on and off on the fly without producing
70
* errors. It also doesn't warn if the disposable objects don't call the
71
* `goog.Disposable` base constructor.
72
*/
73
INTERACTIVE: 2
74
};
75
76
77
/**
78
* @define {number} The monitoring mode of the goog.Disposable
79
* instances. Default is OFF. Switching on the monitoring is only
80
* recommended for debugging because it has a significant impact on
81
* performance and memory usage. If switched off, the monitoring code
82
* compiles down to 0 bytes.
83
*/
84
goog.Disposable.MONITORING_MODE =
85
goog.define('goog.Disposable.MONITORING_MODE', 0);
86
87
88
/**
89
* @define {boolean} Whether to attach creation stack to each created disposable
90
* instance; This is only relevant for when MonitoringMode != OFF.
91
*/
92
goog.Disposable.INCLUDE_STACK_ON_CREATION =
93
goog.define('goog.Disposable.INCLUDE_STACK_ON_CREATION', true);
94
95
96
/**
97
* Maps the unique ID of every undisposed `goog.Disposable` object to
98
* the object itself.
99
* @type {!Object<number, !goog.Disposable>}
100
* @private
101
*/
102
goog.Disposable.instances_ = {};
103
104
105
/**
106
* @return {!Array<!goog.Disposable>} All `goog.Disposable` objects that
107
* haven't been disposed of.
108
*/
109
goog.Disposable.getUndisposedObjects = function() {
110
'use strict';
111
var ret = [];
112
for (var id in goog.Disposable.instances_) {
113
if (goog.Disposable.instances_.hasOwnProperty(id)) {
114
ret.push(goog.Disposable.instances_[Number(id)]);
115
}
116
}
117
return ret;
118
};
119
120
121
/**
122
* Clears the registry of undisposed objects but doesn't dispose of them.
123
*/
124
goog.Disposable.clearUndisposedObjects = function() {
125
'use strict';
126
goog.Disposable.instances_ = {};
127
};
128
129
130
/**
131
* Whether the object has been disposed of.
132
* @type {boolean}
133
* @private
134
*/
135
goog.Disposable.prototype.disposed_ = false;
136
137
138
/**
139
* Callbacks to invoke when this object is disposed.
140
* @type {Array<!Function>}
141
* @private
142
*/
143
goog.Disposable.prototype.onDisposeCallbacks_;
144
145
146
/**
147
* @return {boolean} Whether the object has been disposed of.
148
* @override
149
*/
150
goog.Disposable.prototype.isDisposed = function() {
151
'use strict';
152
return this.disposed_;
153
};
154
155
156
/**
157
* @return {boolean} Whether the object has been disposed of.
158
* @deprecated Use {@link #isDisposed} instead.
159
*/
160
goog.Disposable.prototype.getDisposed = goog.Disposable.prototype.isDisposed;
161
162
163
/**
164
* Disposes of the object. If the object hasn't already been disposed of, calls
165
* {@link #disposeInternal}. Classes that extend `goog.Disposable` should
166
* override {@link #disposeInternal} in order to cleanup references, resources
167
* and other disposable objects. Reentrant.
168
*
169
* @return {void} Nothing.
170
* @override
171
*/
172
goog.Disposable.prototype.dispose = function() {
173
'use strict';
174
if (!this.disposed_) {
175
// Set disposed_ to true first, in case during the chain of disposal this
176
// gets disposed recursively.
177
this.disposed_ = true;
178
this.disposeInternal();
179
if (goog.Disposable.MONITORING_MODE != goog.Disposable.MonitoringMode.OFF) {
180
var uid = goog.utils.getUid(this);
181
if (goog.Disposable.MONITORING_MODE ==
182
goog.Disposable.MonitoringMode.PERMANENT &&
183
!goog.Disposable.instances_.hasOwnProperty(uid)) {
184
throw new Error(
185
this + ' did not call the goog.Disposable base ' +
186
'constructor or was disposed of after a clearUndisposedObjects ' +
187
'call');
188
}
189
if (goog.Disposable.MONITORING_MODE !=
190
goog.Disposable.MonitoringMode.OFF &&
191
this.onDisposeCallbacks_ && this.onDisposeCallbacks_.length > 0) {
192
throw new Error(
193
this + ' did not empty its onDisposeCallbacks queue. This ' +
194
'probably means it overrode dispose() or disposeInternal() ' +
195
'without calling the superclass\' method.');
196
}
197
delete goog.Disposable.instances_[uid];
198
}
199
}
200
};
201
202
203
/**
204
* Associates a disposable object with this object so that they will be disposed
205
* together.
206
* @param {goog.disposable.IDisposable} disposable that will be disposed when
207
* this object is disposed.
208
*/
209
goog.Disposable.prototype.registerDisposable = function(disposable) {
210
'use strict';
211
this.addOnDisposeCallback(goog.utils.partial(goog.dispose, disposable));
212
};
213
214
215
/**
216
* Invokes a callback function when this object is disposed. Callbacks are
217
* invoked in the order in which they were added. If a callback is added to
218
* an already disposed Disposable, it will be called immediately.
219
* @param {function(this:T):?} callback The callback function.
220
* @param {T=} opt_scope An optional scope to call the callback in.
221
* @template T
222
*/
223
goog.Disposable.prototype.addOnDisposeCallback = function(callback, opt_scope) {
224
'use strict';
225
if (this.disposed_) {
226
opt_scope !== undefined ? callback.call(opt_scope) : callback();
227
return;
228
}
229
if (!this.onDisposeCallbacks_) {
230
this.onDisposeCallbacks_ = [];
231
}
232
233
this.onDisposeCallbacks_.push(
234
opt_scope !== undefined ? goog.utils.bind(callback, opt_scope) : callback);
235
};
236
237
238
/**
239
* Performs appropriate cleanup. See description of goog.disposable.IDisposable
240
* for examples. Classes that extend `goog.Disposable` should override this
241
* method. Not reentrant. To avoid calling it twice, it must only be called from
242
* the subclass' `disposeInternal` method. Everywhere else the public `dispose`
243
* method must be used. For example:
244
*
245
* <pre>
246
* mypackage.MyClass = function() {
247
* mypackage.MyClass.base(this, 'constructor');
248
* // Constructor logic specific to MyClass.
249
* ...
250
* };
251
* goog.inherits(mypackage.MyClass, goog.Disposable);
252
*
253
* mypackage.MyClass.prototype.disposeInternal = function() {
254
* // Dispose logic specific to MyClass.
255
* ...
256
* // Call superclass's disposeInternal at the end of the subclass's, like
257
* // in C++, to avoid hard-to-catch issues.
258
* mypackage.MyClass.base(this, 'disposeInternal');
259
* };
260
* </pre>
261
*
262
* @protected
263
*/
264
goog.Disposable.prototype.disposeInternal = function() {
265
'use strict';
266
if (this.onDisposeCallbacks_) {
267
while (this.onDisposeCallbacks_.length) {
268
this.onDisposeCallbacks_.shift()();
269
}
270
}
271
};
272
273
274
/**
275
* Returns True if we can verify the object is disposed.
276
* Calls `isDisposed` on the argument if it supports it. If obj
277
* is not an object with an isDisposed() method, return false.
278
* @param {*} obj The object to investigate.
279
* @return {boolean} True if we can verify the object is disposed.
280
*/
281
goog.Disposable.isDisposed = function(obj) {
282
'use strict';
283
if (obj && typeof obj.isDisposed == 'function') {
284
return obj.isDisposed();
285
}
286
return false;
287
};
288
289