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