-
Notifications
You must be signed in to change notification settings - Fork 71
/
asserts.js
159 lines (147 loc) · 5.4 KB
/
asserts.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/**
* @license
* Copyright The Closure Library Authors.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview Utilities to check the preconditions, postconditions and
* invariants runtime.
*/
goog.provide('jspb.asserts');
/**
* Throws an exception with the given message and "Assertion failed" prefixed
* onto it.
* @param {string} defaultMessage The message to use if givenMessage is empty.
* @param {?Array<*>} defaultArgs The substitution arguments for defaultMessage.
* @param {string|undefined} givenMessage Message supplied by the caller.
* @param {!Array<*>} givenArgs The substitution arguments for givenMessage.
* @throws {Error} When the value is not a number.
*/
jspb.asserts.doAssertFailure = function(defaultMessage, defaultArgs, givenMessage, givenArgs) {
let message = 'Assertion failed';
let args;
if (givenMessage) {
message += ': ' + givenMessage;
args = givenArgs;
} else if (defaultMessage) {
message += ': ' + defaultMessage;
args = defaultArgs;
}
// The '' + works around an Opera 10 bug in the unit tests. Without it,
// a stack trace is added to var message above. With this, a stack trace is
// not added until this line (it causes the extra garbage to be added after
// the assertion message instead of in the middle of it).
throw new Error('' + message, args || []);
}
/**
* Checks if the condition evaluates to true.
* @template T
* @param {T} condition The condition to check.
* @param {string=} opt_message Error message in case of failure.
* @param {...*} args The items to substitute into the failure message.
* @return {T} The value of the condition.
* @throws {Error} When the condition evaluates to false.
*/
jspb.asserts.assert = function(condition, opt_message, ...args) {
if (!condition) {
jspb.asserts.doAssertFailure('', null, opt_message, args);
}
return condition;
};
/**
* Checks if the value is a string.
* @param {*} value The value to check.
* @param {string=} opt_message Error message in case of failure.
* @param {...*} args The items to substitute into the failure message.
* @return {string} The value, guaranteed to be a string when asserts enabled.
* @throws {Error} When the value is not a string.
*/
jspb.asserts.assertString = function(value, opt_message, ...args) {
if (typeof value !== 'string') {
jspb.asserts.doAssertFailure(
'Expected string but got %s: %s.', [goog.typeOf(value), value],
opt_message, args);
}
return /** @type {string} */ (value);
};
/**
* Checks if the value is an Array.
* @param {*} value The value to check.
* @param {string=} opt_message Error message in case of failure.
* @param {...*} args The items to substitute into the failure message.
* @return {!Array<?>} The value, guaranteed to be a non-null array.
* @throws {Error} When the value is not an array.
*/
jspb.asserts.assertArray = function(value, opt_message, ...args) {
if (!Array.isArray(value)) {
jspb.asserts.doAssertFailure(
'Expected array but got %s: %s.', [goog.typeOf(value), value],
opt_message, args);
}
return /** @type {!Array<?>} */ (value);
};
/**
* Triggers a failure. This function is useful in case when we want to add a
* check in the unreachable area like switch-case statement:
*
* <pre>
* switch(type) {
* case FOO: doSomething(); break;
* case BAR: doSomethingElse(); break;
* default: jspb.asserts.JspbFail('Unrecognized type: ' + type);
* // We have only 2 types - "default:" section is unreachable code.
* }
* </pre>
*
* @param {string=} opt_message Error message in case of failure.
* @param {...*} args The items to substitute into the failure message.
* @return {void}
* @throws {Error} Failure.
*/
jspb.asserts.fail = function(opt_message, ...args) {
throw new Error(
'Failure' + (opt_message ? ': ' + opt_message : ''),
args);
};
/**
* Checks if the value is an instance of the user-defined type.
*
* Do not use this to ensure a value is an HTMLElement or a subclass! Cross-
* document DOM inherits from separate - though identical - browser classes, and
* such a check will unexpectedly fail.
*
* @param {?} value The value to check.
* @param {function(new: T, ...)} type A user-defined constructor.
* @param {string=} opt_message Error message in case of failure.
* @param {...*} args The items to substitute into the failure message.
* @throws {Error} When the value is not an instance of
* type.
* @return {T}
* @template T
*/
jspb.asserts.assertInstanceof = function(value, type, opt_message, ...args) {
if (!(value instanceof type)) {
jspb.asserts.doAssertFailure(
'Expected instanceof %s but got %s.',
[jspb.asserts.getType(type), jspb.asserts.getType(value)],
opt_message, args);
}
return value;
};
/**
* Returns the type of a value. If a constructor is passed, and a suitable
* string cannot be found, 'unknown type name' will be returned.
* @param {*} value A constructor, object, or primitive.
* @return {string} The best display name for the value, or 'unknown type name'.
* @private
*/
jspb.asserts.getType = function(value) {
if (value instanceof Function) {
return value.displayName || value.name || 'unknown type name';
} else if (value instanceof Object) {
return /** @type {string} */ (value.constructor.displayName) ||
value.constructor.name || Object.prototype.toString.call(value);
} else {
return value === null ? 'null' : typeof value;
}
}