Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/asserts/asserts.js
2868 views
1
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS-IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
/**
16
* @fileoverview Utilities to check the preconditions, postconditions and
17
* invariants runtime.
18
*
19
* Methods in this package should be given special treatment by the compiler
20
* for type-inference. For example, <code>goog.asserts.assert(foo)</code>
21
* will restrict <code>foo</code> to a truthy value.
22
*
23
* The compiler has an option to disable asserts. So code like:
24
* <code>
25
* var x = goog.asserts.assert(foo()); goog.asserts.assert(bar());
26
* </code>
27
* will be transformed into:
28
* <code>
29
* var x = foo();
30
* </code>
31
* The compiler will leave in foo() (because its return value is used),
32
* but it will remove bar() because it assumes it does not have side-effects.
33
*
34
* @author [email protected] (Andrew Grieve)
35
*/
36
37
goog.provide('goog.asserts');
38
goog.provide('goog.asserts.AssertionError');
39
40
goog.require('goog.debug.Error');
41
goog.require('goog.dom.NodeType');
42
goog.require('goog.string');
43
44
45
/**
46
* @define {boolean} Whether to strip out asserts or to leave them in.
47
*/
48
goog.define('goog.asserts.ENABLE_ASSERTS', goog.DEBUG);
49
50
51
52
/**
53
* Error object for failed assertions.
54
* @param {string} messagePattern The pattern that was used to form message.
55
* @param {!Array<*>} messageArgs The items to substitute into the pattern.
56
* @constructor
57
* @extends {goog.debug.Error}
58
* @final
59
*/
60
goog.asserts.AssertionError = function(messagePattern, messageArgs) {
61
messageArgs.unshift(messagePattern);
62
goog.debug.Error.call(this, goog.string.subs.apply(null, messageArgs));
63
// Remove the messagePattern afterwards to avoid permanently modifying the
64
// passed in array.
65
messageArgs.shift();
66
67
/**
68
* The message pattern used to format the error message. Error handlers can
69
* use this to uniquely identify the assertion.
70
* @type {string}
71
*/
72
this.messagePattern = messagePattern;
73
};
74
goog.inherits(goog.asserts.AssertionError, goog.debug.Error);
75
76
77
/** @override */
78
goog.asserts.AssertionError.prototype.name = 'AssertionError';
79
80
81
/**
82
* The default error handler.
83
* @param {!goog.asserts.AssertionError} e The exception to be handled.
84
*/
85
goog.asserts.DEFAULT_ERROR_HANDLER = function(e) {
86
throw e;
87
};
88
89
90
/**
91
* The handler responsible for throwing or logging assertion errors.
92
* @private {function(!goog.asserts.AssertionError)}
93
*/
94
goog.asserts.errorHandler_ = goog.asserts.DEFAULT_ERROR_HANDLER;
95
96
97
/**
98
* Throws an exception with the given message and "Assertion failed" prefixed
99
* onto it.
100
* @param {string} defaultMessage The message to use if givenMessage is empty.
101
* @param {Array<*>} defaultArgs The substitution arguments for defaultMessage.
102
* @param {string|undefined} givenMessage Message supplied by the caller.
103
* @param {Array<*>} givenArgs The substitution arguments for givenMessage.
104
* @throws {goog.asserts.AssertionError} When the value is not a number.
105
* @private
106
*/
107
goog.asserts.doAssertFailure_ = function(
108
defaultMessage, defaultArgs, givenMessage, givenArgs) {
109
var message = 'Assertion failed';
110
if (givenMessage) {
111
message += ': ' + givenMessage;
112
var args = givenArgs;
113
} else if (defaultMessage) {
114
message += ': ' + defaultMessage;
115
args = defaultArgs;
116
}
117
// The '' + works around an Opera 10 bug in the unit tests. Without it,
118
// a stack trace is added to var message above. With this, a stack trace is
119
// not added until this line (it causes the extra garbage to be added after
120
// the assertion message instead of in the middle of it).
121
var e = new goog.asserts.AssertionError('' + message, args || []);
122
goog.asserts.errorHandler_(e);
123
};
124
125
126
/**
127
* Sets a custom error handler that can be used to customize the behavior of
128
* assertion failures, for example by turning all assertion failures into log
129
* messages.
130
* @param {function(!goog.asserts.AssertionError)} errorHandler
131
*/
132
goog.asserts.setErrorHandler = function(errorHandler) {
133
if (goog.asserts.ENABLE_ASSERTS) {
134
goog.asserts.errorHandler_ = errorHandler;
135
}
136
};
137
138
139
/**
140
* Checks if the condition evaluates to true if goog.asserts.ENABLE_ASSERTS is
141
* true.
142
* @template T
143
* @param {T} condition The condition to check.
144
* @param {string=} opt_message Error message in case of failure.
145
* @param {...*} var_args The items to substitute into the failure message.
146
* @return {T} The value of the condition.
147
* @throws {goog.asserts.AssertionError} When the condition evaluates to false.
148
*/
149
goog.asserts.assert = function(condition, opt_message, var_args) {
150
if (goog.asserts.ENABLE_ASSERTS && !condition) {
151
goog.asserts.doAssertFailure_(
152
'', null, opt_message, Array.prototype.slice.call(arguments, 2));
153
}
154
return condition;
155
};
156
157
158
/**
159
* Fails if goog.asserts.ENABLE_ASSERTS is true. This function is useful in case
160
* when we want to add a check in the unreachable area like switch-case
161
* statement:
162
*
163
* <pre>
164
* switch(type) {
165
* case FOO: doSomething(); break;
166
* case BAR: doSomethingElse(); break;
167
* default: goog.asserts.fail('Unrecognized type: ' + type);
168
* // We have only 2 types - "default:" section is unreachable code.
169
* }
170
* </pre>
171
*
172
* @param {string=} opt_message Error message in case of failure.
173
* @param {...*} var_args The items to substitute into the failure message.
174
* @throws {goog.asserts.AssertionError} Failure.
175
*/
176
goog.asserts.fail = function(opt_message, var_args) {
177
if (goog.asserts.ENABLE_ASSERTS) {
178
goog.asserts.errorHandler_(
179
new goog.asserts.AssertionError(
180
'Failure' + (opt_message ? ': ' + opt_message : ''),
181
Array.prototype.slice.call(arguments, 1)));
182
}
183
};
184
185
186
/**
187
* Checks if the value is a number if goog.asserts.ENABLE_ASSERTS is true.
188
* @param {*} value The value to check.
189
* @param {string=} opt_message Error message in case of failure.
190
* @param {...*} var_args The items to substitute into the failure message.
191
* @return {number} The value, guaranteed to be a number when asserts enabled.
192
* @throws {goog.asserts.AssertionError} When the value is not a number.
193
*/
194
goog.asserts.assertNumber = function(value, opt_message, var_args) {
195
if (goog.asserts.ENABLE_ASSERTS && !goog.isNumber(value)) {
196
goog.asserts.doAssertFailure_(
197
'Expected number but got %s: %s.', [goog.typeOf(value), value],
198
opt_message, Array.prototype.slice.call(arguments, 2));
199
}
200
return /** @type {number} */ (value);
201
};
202
203
204
/**
205
* Checks if the value is a string if goog.asserts.ENABLE_ASSERTS is true.
206
* @param {*} value The value to check.
207
* @param {string=} opt_message Error message in case of failure.
208
* @param {...*} var_args The items to substitute into the failure message.
209
* @return {string} The value, guaranteed to be a string when asserts enabled.
210
* @throws {goog.asserts.AssertionError} When the value is not a string.
211
*/
212
goog.asserts.assertString = function(value, opt_message, var_args) {
213
if (goog.asserts.ENABLE_ASSERTS && !goog.isString(value)) {
214
goog.asserts.doAssertFailure_(
215
'Expected string but got %s: %s.', [goog.typeOf(value), value],
216
opt_message, Array.prototype.slice.call(arguments, 2));
217
}
218
return /** @type {string} */ (value);
219
};
220
221
222
/**
223
* Checks if the value is a function if goog.asserts.ENABLE_ASSERTS is true.
224
* @param {*} value The value to check.
225
* @param {string=} opt_message Error message in case of failure.
226
* @param {...*} var_args The items to substitute into the failure message.
227
* @return {!Function} The value, guaranteed to be a function when asserts
228
* enabled.
229
* @throws {goog.asserts.AssertionError} When the value is not a function.
230
*/
231
goog.asserts.assertFunction = function(value, opt_message, var_args) {
232
if (goog.asserts.ENABLE_ASSERTS && !goog.isFunction(value)) {
233
goog.asserts.doAssertFailure_(
234
'Expected function but got %s: %s.', [goog.typeOf(value), value],
235
opt_message, Array.prototype.slice.call(arguments, 2));
236
}
237
return /** @type {!Function} */ (value);
238
};
239
240
241
/**
242
* Checks if the value is an Object if goog.asserts.ENABLE_ASSERTS is true.
243
* @param {*} value The value to check.
244
* @param {string=} opt_message Error message in case of failure.
245
* @param {...*} var_args The items to substitute into the failure message.
246
* @return {!Object} The value, guaranteed to be a non-null object.
247
* @throws {goog.asserts.AssertionError} When the value is not an object.
248
*/
249
goog.asserts.assertObject = function(value, opt_message, var_args) {
250
if (goog.asserts.ENABLE_ASSERTS && !goog.isObject(value)) {
251
goog.asserts.doAssertFailure_(
252
'Expected object but got %s: %s.', [goog.typeOf(value), value],
253
opt_message, Array.prototype.slice.call(arguments, 2));
254
}
255
return /** @type {!Object} */ (value);
256
};
257
258
259
/**
260
* Checks if the value is an Array if goog.asserts.ENABLE_ASSERTS is true.
261
* @param {*} value The value to check.
262
* @param {string=} opt_message Error message in case of failure.
263
* @param {...*} var_args The items to substitute into the failure message.
264
* @return {!Array<?>} The value, guaranteed to be a non-null array.
265
* @throws {goog.asserts.AssertionError} When the value is not an array.
266
*/
267
goog.asserts.assertArray = function(value, opt_message, var_args) {
268
if (goog.asserts.ENABLE_ASSERTS && !goog.isArray(value)) {
269
goog.asserts.doAssertFailure_(
270
'Expected array but got %s: %s.', [goog.typeOf(value), value],
271
opt_message, Array.prototype.slice.call(arguments, 2));
272
}
273
return /** @type {!Array<?>} */ (value);
274
};
275
276
277
/**
278
* Checks if the value is a boolean if goog.asserts.ENABLE_ASSERTS is true.
279
* @param {*} value The value to check.
280
* @param {string=} opt_message Error message in case of failure.
281
* @param {...*} var_args The items to substitute into the failure message.
282
* @return {boolean} The value, guaranteed to be a boolean when asserts are
283
* enabled.
284
* @throws {goog.asserts.AssertionError} When the value is not a boolean.
285
*/
286
goog.asserts.assertBoolean = function(value, opt_message, var_args) {
287
if (goog.asserts.ENABLE_ASSERTS && !goog.isBoolean(value)) {
288
goog.asserts.doAssertFailure_(
289
'Expected boolean but got %s: %s.', [goog.typeOf(value), value],
290
opt_message, Array.prototype.slice.call(arguments, 2));
291
}
292
return /** @type {boolean} */ (value);
293
};
294
295
296
/**
297
* Checks if the value is a DOM Element if goog.asserts.ENABLE_ASSERTS is true.
298
* @param {*} value The value to check.
299
* @param {string=} opt_message Error message in case of failure.
300
* @param {...*} var_args The items to substitute into the failure message.
301
* @return {!Element} The value, likely to be a DOM Element when asserts are
302
* enabled.
303
* @throws {goog.asserts.AssertionError} When the value is not an Element.
304
*/
305
goog.asserts.assertElement = function(value, opt_message, var_args) {
306
if (goog.asserts.ENABLE_ASSERTS &&
307
(!goog.isObject(value) || value.nodeType != goog.dom.NodeType.ELEMENT)) {
308
goog.asserts.doAssertFailure_(
309
'Expected Element but got %s: %s.', [goog.typeOf(value), value],
310
opt_message, Array.prototype.slice.call(arguments, 2));
311
}
312
return /** @type {!Element} */ (value);
313
};
314
315
316
/**
317
* Checks if the value is an instance of the user-defined type if
318
* goog.asserts.ENABLE_ASSERTS is true.
319
*
320
* The compiler may tighten the type returned by this function.
321
*
322
* @param {?} value The value to check.
323
* @param {function(new: T, ...)} type A user-defined constructor.
324
* @param {string=} opt_message Error message in case of failure.
325
* @param {...*} var_args The items to substitute into the failure message.
326
* @throws {goog.asserts.AssertionError} When the value is not an instance of
327
* type.
328
* @return {T}
329
* @template T
330
*/
331
goog.asserts.assertInstanceof = function(value, type, opt_message, var_args) {
332
if (goog.asserts.ENABLE_ASSERTS && !(value instanceof type)) {
333
goog.asserts.doAssertFailure_(
334
'Expected instanceof %s but got %s.',
335
[goog.asserts.getType_(type), goog.asserts.getType_(value)],
336
opt_message, Array.prototype.slice.call(arguments, 3));
337
}
338
return value;
339
};
340
341
342
/**
343
* Checks that no enumerable keys are present in Object.prototype. Such keys
344
* would break most code that use {@code for (var ... in ...)} loops.
345
*/
346
goog.asserts.assertObjectPrototypeIsIntact = function() {
347
for (var key in Object.prototype) {
348
goog.asserts.fail(key + ' should not be enumerable in Object.prototype.');
349
}
350
};
351
352
353
/**
354
* Returns the type of a value. If a constructor is passed, and a suitable
355
* string cannot be found, 'unknown type name' will be returned.
356
* @param {*} value A constructor, object, or primitive.
357
* @return {string} The best display name for the value, or 'unknown type name'.
358
* @private
359
*/
360
goog.asserts.getType_ = function(value) {
361
if (value instanceof Function) {
362
return value.displayName || value.name || 'unknown type name';
363
} else if (value instanceof Object) {
364
return value.constructor.displayName || value.constructor.name ||
365
Object.prototype.toString.call(value);
366
} else {
367
return value === null ? 'null' : typeof value;
368
}
369
};
370
371