# lib/goog/base.js

    1// Copyright 2006 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 at6//7//      http://www.apache.org/licenses/LICENSE-2.08//9// Unless required by applicable law or agreed to in writing, software10// 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 and13// limitations under the License.1415/**16 * @fileoverview Bootstrap for the Google JS Library (Closure).17 *18 * In uncompiled mode base.js will write out Closure's deps file, unless the19 * global <code>CLOSURE_NO_DEPS</code> is set to true.  This allows projects to20 * include their own deps file(s) from different locations.21 *22 *23 * @provideGoog24 */252627/**28 * @define {boolean} Overridden to true by the compiler when --closure_pass29 *     or --mark_as_compiled is specified.30 */31var COMPILED = false;323334/**35 * Base namespace for the Closure library.  Checks to see goog is already36 * defined in the current scope before assigning to prevent clobbering if37 * base.js is loaded more than once.38 *39 * @const40 */41var goog = goog || {};424344/**45 * Reference to the global context.  In most cases this will be 'window'.46 */47goog.global = this;484950/**51 * A hook for overriding the define values in uncompiled mode.52 *53 * In uncompiled mode, {@code CLOSURE_UNCOMPILED_DEFINES} may be defined before54 * loading base.js.  If a key is defined in {@code CLOSURE_UNCOMPILED_DEFINES},55 * {@code goog.define} will use the value instead of the default value.  This56 * allows flags to be overwritten without compilation (this is normally57 * accomplished with the compiler's "define" flag).58 *59 * Example:60 * <pre>61 *   var CLOSURE_UNCOMPILED_DEFINES = {'goog.DEBUG': false};62 * </pre>63 *64 * @type {Object.<string, (string|number|boolean)>|undefined}65 */66goog.global.CLOSURE_UNCOMPILED_DEFINES;676869/**70 * A hook for overriding the define values in uncompiled or compiled mode,71 * like CLOSURE_UNCOMPILED_DEFINES but effective in compiled code.  In72 * uncompiled code CLOSURE_UNCOMPILED_DEFINES takes precedence.73 *74 * Also unlike CLOSURE_UNCOMPILED_DEFINES the values must be number, boolean or75 * string literals or the compiler will emit an error.76 *77 * While any @define value may be set, only those set with goog.define will be78 * effective for uncompiled code.79 *80 * Example:81 * <pre>82 *   var CLOSURE_DEFINES = {'goog.DEBUG': false};83 * </pre>84 *85 * @type {Object.<string, (string|number|boolean)>|undefined}86 */87goog.global.CLOSURE_DEFINES;888990/**91 * Returns true if the specified value is not undefined.92 * WARNING: Do not use this to test if an object has a property. Use the in93 * operator instead.94 *95 * @param {?} val Variable to test.96 * @return {boolean} Whether variable is defined.97 */98goog.isDef = function(val) {99  // void 0 always evaluates to undefined and hence we do not need to depend on100  // the definition of the global variable named 'undefined'.101  return val !== void 0;102};103104105/**106 * Builds an object structure for the provided namespace path, ensuring that107 * names that already exist are not overwritten. For example:108 * "a.b.c" -> a = {};a.b={};a.b.c={};109 * Used by goog.provide and goog.exportSymbol.110 * @param {string} name name of the object that this file defines.111 * @param {*=} opt_object the object to expose at the end of the path.112 * @param {Object=} opt_objectToExportTo The object to add the path to; default113 *     is |goog.global|.114 * @private115 */116goog.exportPath_ = function(name, opt_object, opt_objectToExportTo) {117  var parts = name.split('.');118  var cur = opt_objectToExportTo || goog.global;119120  // Internet Explorer exhibits strange behavior when throwing errors from121  // methods externed in this manner.  See the testExportSymbolExceptions in122  // base_test.html for an example.123  if (!(parts[0] in cur) && cur.execScript) {124    cur.execScript('var ' + parts[0]);125  }126127  // Certain browsers cannot parse code in the form for((a in b); c;);128  // This pattern is produced by the JSCompiler when it collapses the129  // statement above into the conditional loop below. To prevent this from130  // happening, use a for-loop and reserve the init logic as below.131132  // Parentheses added to eliminate strict JS warning in Firefox.133  for (var part; parts.length && (part = parts.shift());) {134    if (!parts.length && goog.isDef(opt_object)) {135      // last part and we have an object; use it136      cur[part] = opt_object;137    } else if (cur[part]) {138      cur = cur[part];139    } else {140      cur = cur[part] = {};141    }142  }143};144145146/**147 * Defines a named value. In uncompiled mode, the value is retreived from148 * CLOSURE_DEFINES or CLOSURE_UNCOMPILED_DEFINES if the object is defined and149 * has the property specified, and otherwise used the defined defaultValue.150 * When compiled, the default can be overridden using compiler command-line151 * options.152 *153 * @param {string} name The distinguished name to provide.154 * @param {string|number|boolean} defaultValue155 */156goog.define = function(name, defaultValue) {157  var value = defaultValue;158  if (!COMPILED) {159    if (goog.global.CLOSURE_UNCOMPILED_DEFINES &&160        Object.prototype.hasOwnProperty.call(161            goog.global.CLOSURE_UNCOMPILED_DEFINES, name)) {162      value = goog.global.CLOSURE_UNCOMPILED_DEFINES[name];163    } else if (goog.global.CLOSURE_DEFINES &&164        Object.prototype.hasOwnProperty.call(165            goog.global.CLOSURE_DEFINES, name)) {166      value = goog.global.CLOSURE_DEFINES[name];167    }168  }169  goog.exportPath_(name, value);170};171172173/**174 * @define {boolean} DEBUG is provided as a convenience so that debugging code175 * that should not be included in a production js_binary can be easily stripped176 * by specifying --define goog.DEBUG=false to the JSCompiler. For example, most177 * toString() methods should be declared inside an "if (goog.DEBUG)" conditional178 * because they are generally used for debugging purposes and it is difficult179 * for the JSCompiler to statically determine whether they are used.180 */181goog.DEBUG = true;182183184/**185 * @define {string} LOCALE defines the locale being used for compilation. It is186 * used to select locale specific data to be compiled in js binary. BUILD rule187 * can specify this value by "--define goog.LOCALE=<locale_name>" as JSCompiler188 * option.189 *190 * Take into account that the locale code format is important. You should use191 * the canonical Unicode format with hyphen as a delimiter. Language must be192 * lowercase, Language Script - Capitalized, Region - UPPERCASE.193 * There are few examples: pt-BR, en, en-US, sr-Latin-BO, zh-Hans-CN.194 *195 * See more info about locale codes here:196 * http://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers197 *198 * For language codes you should use values defined by ISO 693-1. See it here199 * http://www.w3.org/WAI/ER/IG/ert/iso639.htm. There is only one exception from200 * this rule: the Hebrew language. For legacy reasons the old code (iw) should201 * be used instead of the new code (he), see http://wiki/Main/IIISynonyms.202 */203goog.define('goog.LOCALE', 'en');  // default to en204205206/**207 * @define {boolean} Whether this code is running on trusted sites.208 *209 * On untrusted sites, several native functions can be defined or overridden by210 * external libraries like Prototype, Datejs, and JQuery and setting this flag211 * to false forces closure to use its own implementations when possible.212 *213 * If your JavaScript can be loaded by a third party site and you are wary about214 * relying on non-standard implementations, specify215 * "--define goog.TRUSTED_SITE=false" to the JSCompiler.216 */217goog.define('goog.TRUSTED_SITE', true);218219220/**221 * @define {boolean} Whether a project is expected to be running in strict mode.222 *223 * This define can be used to trigger alternate implementations compatible with224 * running in EcmaScript Strict mode or warn about unavailable functionality.225 * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode226 */227goog.define('goog.STRICT_MODE_COMPATIBLE', false);228229230/**231 * Creates object stubs for a namespace.  The presence of one or more232 * goog.provide() calls indicate that the file defines the given233 * objects/namespaces.  Provided objects must not be null or undefined.234 * Build tools also scan for provide/require statements235 * to discern dependencies, build dependency files (see deps.js), etc.236 * @see goog.require237 * @param {string} name Namespace provided by this file in the form238 *     "goog.package.part".239 */240goog.provide = function(name) {241  if (!COMPILED) {242    // Ensure that the same namespace isn't provided twice. This is intended243    // to teach new developers that 'goog.provide' is effectively a variable244    // declaration. And when JSCompiler transforms goog.provide into a real245    // variable declaration, the compiled JS should work the same as the raw246    // JS--even when the raw JS uses goog.provide incorrectly.247    if (goog.isProvided_(name)) {248      throw Error('Namespace "' + name + '" already declared.');249    }250    delete goog.implicitNamespaces_[name];251252    var namespace = name;253    while ((namespace = namespace.substring(0, namespace.lastIndexOf('.')))) {254      if (goog.getObjectByName(namespace)) {255        break;256      }257      goog.implicitNamespaces_[namespace] = true;258    }259  }260261  goog.exportPath_(name);262};263264265/**266 * Marks that the current file should only be used for testing, and never for267 * live code in production.268 *269 * In the case of unit tests, the message may optionally be an exact namespace270 * for the test (e.g. 'goog.stringTest'). The linter will then ignore the extra271 * provide (if not explicitly defined in the code).272 *273 * @param {string=} opt_message Optional message to add to the error that's274 *     raised when used in production code.275 */276goog.setTestOnly = function(opt_message) {277  if (COMPILED && !goog.DEBUG) {278    opt_message = opt_message || '';279    throw Error('Importing test-only code into non-debug environment' +280                opt_message ? ': ' + opt_message : '.');281  }282};283284285/**286 * Forward declares a symbol. This is an indication to the compiler that the287 * symbol may be used in the source yet is not required and may not be provided288 * in compilation.289 *290 * The most common usage of forward declaration is code that takes a type as a291 * function parameter but does not need to require it. By forward declaring292 * instead of requiring, no hard dependency is made, and (if not required293 * elsewhere) the namespace may never be required and thus, not be pulled294 * into the JavaScript binary. If it is required elsewhere, it will be type295 * checked as normal.296 *297 *298 * @param {string} name The namespace to forward declare in the form of299 *     "goog.package.part".300 */301goog.forwardDeclare = function(name) {};302303304if (!COMPILED) {305306  /**307   * Check if the given name has been goog.provided. This will return false for308   * names that are available only as implicit namespaces.309   * @param {string} name name of the object to look for.310   * @return {boolean} Whether the name has been provided.311   * @private312   */313  goog.isProvided_ = function(name) {314    return !goog.implicitNamespaces_[name] &&315        goog.isDefAndNotNull(goog.getObjectByName(name));316  };317318  /**319   * Namespaces implicitly defined by goog.provide. For example,320   * goog.provide('goog.events.Event') implicitly declares that 'goog' and321   * 'goog.events' must be namespaces.322   *323   * @type {Object}324   * @private325   */326  goog.implicitNamespaces_ = {};327}328329330/**331 * Returns an object based on its fully qualified external name.  The object332 * is not found if null or undefined.  If you are using a compilation pass that333 * renames property names beware that using this function will not find renamed334 * properties.335 *336 * @param {string} name The fully qualified name.337 * @param {Object=} opt_obj The object within which to look; default is338 *     |goog.global|.339 * @return {?} The value (object or primitive) or, if not found, null.340 */341goog.getObjectByName = function(name, opt_obj) {342  var parts = name.split('.');343  var cur = opt_obj || goog.global;344  for (var part; part = parts.shift(); ) {345    if (goog.isDefAndNotNull(cur[part])) {346      cur = cur[part];347    } else {348      return null;349    }350  }351  return cur;352};353354355/**356 * Globalizes a whole namespace, such as goog or goog.lang.357 *358 * @param {Object} obj The namespace to globalize.359 * @param {Object=} opt_global The object to add the properties to.360 * @deprecated Properties may be explicitly exported to the global scope, but361 *     this should no longer be done in bulk.362 */363goog.globalize = function(obj, opt_global) {364  var global = opt_global || goog.global;365  for (var x in obj) {366    global[x] = obj[x];367  }368};369370371/**372 * Adds a dependency from a file to the files it requires.373 * @param {string} relPath The path to the js file.374 * @param {Array} provides An array of strings with the names of the objects375 *                         this file provides.376 * @param {Array} requires An array of strings with the names of the objects377 *                         this file requires.378 */379goog.addDependency = function(relPath, provides, requires) {380  if (goog.DEPENDENCIES_ENABLED) {381    var provide, require;382    var path = relPath.replace(/\\/g, '/');383    var deps = goog.dependencies_;384    for (var i = 0; provide = provides[i]; i++) {385      deps.nameToPath[provide] = path;386      if (!(path in deps.pathToNames)) {387        deps.pathToNames[path] = {};388      }389      deps.pathToNames[path][provide] = true;390    }391    for (var j = 0; require = requires[j]; j++) {392      if (!(path in deps.requires)) {393        deps.requires[path] = {};394      }395      deps.requires[path][require] = true;396    }397  }398};399400401402403// NOTE(nnaze): The debug DOM loader was included in base.js as an original way404// to do "debug-mode" development.  The dependency system can sometimes be405// confusing, as can the debug DOM loader's asynchronous nature.406//407// With the DOM loader, a call to goog.require() is not blocking -- the script408// will not load until some point after the current script.  If a namespace is409// needed at runtime, it needs to be defined in a previous script, or loaded via410// require() with its registered dependencies.411// User-defined namespaces may need their own deps file.  See http://go/js_deps,412// http://go/genjsdeps, or, externally, DepsWriter.413// http://code.google.com/closure/library/docs/depswriter.html414//415// Because of legacy clients, the DOM loader can't be easily removed from416// base.js.  Work is being done to make it disableable or replaceable for417// different environments (DOM-less JavaScript interpreters like Rhino or V8,418// for example). See bootstrap/ for more information.419420421/**422 * @define {boolean} Whether to enable the debug loader.423 *424 * If enabled, a call to goog.require() will attempt to load the namespace by425 * appending a script tag to the DOM (if the namespace has been registered).426 *427 * If disabled, goog.require() will simply assert that the namespace has been428 * provided (and depend on the fact that some outside tool correctly ordered429 * the script).430 */431goog.define('goog.ENABLE_DEBUG_LOADER', true);432433434/**435 * Implements a system for the dynamic resolution of dependencies that works in436 * parallel with the BUILD system. Note that all calls to goog.require will be437 * stripped by the JSCompiler when the --closure_pass option is used.438 * @see goog.provide439 * @param {string} name Namespace to include (as was given in goog.provide()) in440 *     the form "goog.package.part".441 */442goog.require = function(name) {443444  // If the object already exists we do not need do do anything.445  // TODO(arv): If we start to support require based on file name this has to446  //            change.447  // TODO(arv): If we allow goog.foo.* this has to change.448  // TODO(arv): If we implement dynamic load after page load we should probably449  //            not remove this code for the compiled output.450  if (!COMPILED) {451    if (goog.isProvided_(name)) {452      return;453    }454455    if (goog.ENABLE_DEBUG_LOADER) {456      var path = goog.getPathFromDeps_(name);457      if (path) {458        goog.included_[path] = true;459        goog.writeScripts_();460        return;461      }462    }463464    var errorMessage = 'goog.require could not find: ' + name;465    if (goog.global.console) {466      goog.global.console['error'](errorMessage);467    }468469470      throw Error(errorMessage);471472  }473};474475476/**477 * Path for included scripts.478 * @type {string}479 */480goog.basePath = '';481482483/**484 * A hook for overriding the base path.485 * @type {string|undefined}486 */487goog.global.CLOSURE_BASE_PATH;488489490/**491 * Whether to write out Closure's deps file. By default, the deps are written.492 * @type {boolean|undefined}493 */494goog.global.CLOSURE_NO_DEPS;495496497/**498 * A function to import a single script. This is meant to be overridden when499 * Closure is being run in non-HTML contexts, such as web workers. It's defined500 * in the global scope so that it can be set before base.js is loaded, which501 * allows deps.js to be imported properly.502 *503 * The function is passed the script source, which is a relative URI. It should504 * return true if the script was imported, false otherwise.505 * @type {(function(string): boolean)|undefined}506 */507goog.global.CLOSURE_IMPORT_SCRIPT;508509510/**511 * Null function used for default values of callbacks, etc.512 * @return {void} Nothing.513 */514goog.nullFunction = function() {};515516517/**518 * The identity function. Returns its first argument.519 *520 * @param {*=} opt_returnValue The single value that will be returned.521 * @param {...*} var_args Optional trailing arguments. These are ignored.522 * @return {?} The first argument. We can't know the type -- just pass it along523 *      without type.524 * @deprecated Use goog.functions.identity instead.525 */526goog.identityFunction = function(opt_returnValue, var_args) {527  return opt_returnValue;528};529530531/**532 * When defining a class Foo with an abstract method bar(), you can do:533 * Foo.prototype.bar = goog.abstractMethod534 *535 * Now if a subclass of Foo fails to override bar(), an error will be thrown536 * when bar() is invoked.537 *538 * Note: This does not take the name of the function to override as an argument539 * because that would make it more difficult to obfuscate our JavaScript code.540 *541 * @type {!Function}542 * @throws {Error} when invoked to indicate the method should be overridden.543 */544goog.abstractMethod = function() {545  throw Error('unimplemented abstract method');546};547548549/**550 * Adds a {@code getInstance} static method that always returns the same551 * instance object.552 * @param {!Function} ctor The constructor for the class to add the static553 *     method to.554 */555goog.addSingletonGetter = function(ctor) {556  ctor.getInstance = function() {557    if (ctor.instance_) {558      return ctor.instance_;559    }560    if (goog.DEBUG) {561      // NOTE: JSCompiler can't optimize away Array#push.562      goog.instantiatedSingletons_[goog.instantiatedSingletons_.length] = ctor;563    }564    return ctor.instance_ = new ctor;565  };566};567568569/**570 * All singleton classes that have been instantiated, for testing. Don't read571 * it directly, use the {@code goog.testing.singleton} module. The compiler572 * removes this variable if unused.573 * @type {!Array.<!Function>}574 * @private575 */576goog.instantiatedSingletons_ = [];577578579/**580 * True if goog.dependencies_ is available.581 * @const {boolean}582 */583goog.DEPENDENCIES_ENABLED = !COMPILED && goog.ENABLE_DEBUG_LOADER;584585586if (goog.DEPENDENCIES_ENABLED) {587  /**588   * Object used to keep track of urls that have already been added. This record589   * allows the prevention of circular dependencies.590   * @type {Object}591   * @private592   */593  goog.included_ = {};594595596  /**597   * This object is used to keep track of dependencies and other data that is598   * used for loading scripts.599   * @private600   * @type {Object}601   */602  goog.dependencies_ = {603    pathToNames: {}, // 1 to many604    nameToPath: {}, // 1 to 1605    requires: {}, // 1 to many606    // Used when resolving dependencies to prevent us from visiting file twice.607    visited: {},608    written: {} // Used to keep track of script files we have written.609  };610611612  /**613   * Tries to detect whether is in the context of an HTML document.614   * @return {boolean} True if it looks like HTML document.615   * @private616   */617  goog.inHtmlDocument_ = function() {618    var doc = goog.global.document;619    return typeof doc != 'undefined' &&620           'write' in doc;  // XULDocument misses write.621  };622623624  /**625   * Tries to detect the base path of base.js script that bootstraps Closure.626   * @private627   */628  goog.findBasePath_ = function() {629    if (goog.global.CLOSURE_BASE_PATH) {630      goog.basePath = goog.global.CLOSURE_BASE_PATH;631      return;632    } else if (!goog.inHtmlDocument_()) {633      return;634    }635    var doc = goog.global.document;636    var scripts = doc.getElementsByTagName('script');637    // Search backwards since the current script is in almost all cases the one638    // that has base.js.639    for (var i = scripts.length - 1; i >= 0; --i) {640      var src = scripts[i].src;641      var qmark = src.lastIndexOf('?');642      var l = qmark == -1 ? src.length : qmark;643      if (src.substr(l - 7, 7) == 'base.js') {644        goog.basePath = src.substr(0, l - 7);645        return;646      }647    }648  };649650651  /**652   * Imports a script if, and only if, that script hasn't already been imported.653   * (Must be called at execution time)654   * @param {string} src Script source.655   * @private656   */657  goog.importScript_ = function(src) {658    var importScript = goog.global.CLOSURE_IMPORT_SCRIPT ||659        goog.writeScriptTag_;660    if (!goog.dependencies_.written[src] && importScript(src)) {661      goog.dependencies_.written[src] = true;662    }663  };664665666  /**667   * The default implementation of the import function. Writes a script tag to668   * import the script.669   *670   * @param {string} src The script source.671   * @return {boolean} True if the script was imported, false otherwise.672   * @private673   */674  goog.writeScriptTag_ = function(src) {675    if (goog.inHtmlDocument_()) {676      var doc = goog.global.document;677678      // If the user tries to require a new symbol after document load,679      // something has gone terribly wrong. Doing a document.write would680      // wipe out the page.681      if (doc.readyState == 'complete') {682        // Certain test frameworks load base.js multiple times, which tries683        // to write deps.js each time. If that happens, just fail silently.684        // These frameworks wipe the page between each load of base.js, so this685        // is OK.686        var isDeps = /\bdeps.js$/.test(src);687        if (isDeps) {688          return false;689        } else {690          throw Error('Cannot write "' + src + '" after document load');691        }692      }693694      doc.write(695          '<script type="text/javascript" src="' + src + '"></' + 'script>');696      return true;697    } else {698      return false;699    }700  };701702703  /**704   * Resolves dependencies based on the dependencies added using addDependency705   * and calls importScript_ in the correct order.706   * @private707   */708  goog.writeScripts_ = function() {709    // The scripts we need to write this time.710    var scripts = [];711    var seenScript = {};712    var deps = goog.dependencies_;713714    function visitNode(path) {715      if (path in deps.written) {716        return;717      }718719      // We have already visited this one. We can get here if we have cyclic720      // dependencies.721      if (path in deps.visited) {722        if (!(path in seenScript)) {723          seenScript[path] = true;724          scripts.push(path);725        }726        return;727      }728729      deps.visited[path] = true;730731      if (path in deps.requires) {732        for (var requireName in deps.requires[path]) {733          // If the required name is defined, we assume that it was already734          // bootstrapped by other means.735          if (!goog.isProvided_(requireName)) {736            if (requireName in deps.nameToPath) {737              visitNode(deps.nameToPath[requireName]);738            } else {739              throw Error('Undefined nameToPath for ' + requireName);740            }741          }742        }743      }744745      if (!(path in seenScript)) {746        seenScript[path] = true;747        scripts.push(path);748      }749    }750751    for (var path in goog.included_) {752      if (!deps.written[path]) {753        visitNode(path);754      }755    }756757    for (var i = 0; i < scripts.length; i++) {758      if (scripts[i]) {759        goog.importScript_(goog.basePath + scripts[i]);760      } else {761        throw Error('Undefined script input');762      }763    }764  };765766767  /**768   * Looks at the dependency rules and tries to determine the script file that769   * fulfills a particular rule.770   * @param {string} rule In the form goog.namespace.Class or project.script.771   * @return {?string} Url corresponding to the rule, or null.772   * @private773   */774  goog.getPathFromDeps_ = function(rule) {775    if (rule in goog.dependencies_.nameToPath) {776      return goog.dependencies_.nameToPath[rule];777    } else {778      return null;779    }780  };781782  goog.findBasePath_();783784  // Allow projects to manage the deps files themselves.785  if (!goog.global.CLOSURE_NO_DEPS) {786    goog.importScript_(goog.basePath + 'deps.js');787  }788}789790791792//==============================================================================793// Language Enhancements794//==============================================================================795796797/**798 * This is a "fixed" version of the typeof operator.  It differs from the typeof799 * operator in such a way that null returns 'null' and arrays return 'array'.800 * @param {*} value The value to get the type of.801 * @return {string} The name of the type.802 */803goog.typeOf = function(value) {804  var s = typeof value;805  if (s == 'object') {806    if (value) {807      // Check these first, so we can avoid calling Object.prototype.toString if808      // possible.809      //810      // IE improperly marshals tyepof across execution contexts, but a811      // cross-context object will still return false for "instanceof Object".812      if (value instanceof Array) {813        return 'array';814      } else if (value instanceof Object) {815        return s;816      }817818      // HACK: In order to use an Object prototype method on the arbitrary819      //   value, the compiler requires the value be cast to type Object,820      //   even though the ECMA spec explicitly allows it.821      var className = Object.prototype.toString.call(822          /** @type {Object} */ (value));823      // In Firefox 3.6, attempting to access iframe window objects' length824      // property throws an NS_ERROR_FAILURE, so we need to special-case it825      // here.826      if (className == '[object Window]') {827        return 'object';828      }829830      // We cannot always use constructor == Array or instanceof Array because831      // different frames have different Array objects. In IE6, if the iframe832      // where the array was created is destroyed, the array loses its833      // prototype. Then dereferencing val.splice here throws an exception, so834      // we can't use goog.isFunction. Calling typeof directly returns 'unknown'835      // so that will work. In this case, this function will return false and836      // most array functions will still work because the array is still837      // array-like (supports length and []) even though it has lost its838      // prototype.839      // Mark Miller noticed that Object.prototype.toString840      // allows access to the unforgeable [[Class]] property.841      //  15.2.4.2 Object.prototype.toString ( )842      //  When the toString method is called, the following steps are taken:843      //      1. Get the [[Class]] property of this object.844      //      2. Compute a string value by concatenating the three strings845      //         "[object ", Result(1), and "]".846      //      3. Return Result(2).847      // and this behavior survives the destruction of the execution context.848      if ((className == '[object Array]' ||849           // In IE all non value types are wrapped as objects across window850           // boundaries (not iframe though) so we have to do object detection851           // for this edge case.852           typeof value.length == 'number' &&853           typeof value.splice != 'undefined' &&854           typeof value.propertyIsEnumerable != 'undefined' &&855           !value.propertyIsEnumerable('splice')856857          )) {858        return 'array';859      }860      // HACK: There is still an array case that fails.861      //     function ArrayImpostor() {}862      //     ArrayImpostor.prototype = [];863      //     var impostor = new ArrayImpostor;864      // this can be fixed by getting rid of the fast path865      // (value instanceof Array) and solely relying on866      // (value && Object.prototype.toString.vall(value) === '[object Array]')867      // but that would require many more function calls and is not warranted868      // unless closure code is receiving objects from untrusted sources.869870      // IE in cross-window calls does not correctly marshal the function type871      // (it appears just as an object) so we cannot use just typeof val ==872      // 'function'. However, if the object has a call property, it is a873      // function.874      if ((className == '[object Function]' ||875          typeof value.call != 'undefined' &&876          typeof value.propertyIsEnumerable != 'undefined' &&877          !value.propertyIsEnumerable('call'))) {878        return 'function';879      }880881    } else {882      return 'null';883    }884885  } else if (s == 'function' && typeof value.call == 'undefined') {886    // In Safari typeof nodeList returns 'function', and on Firefox typeof887    // behaves similarly for HTML{Applet,Embed,Object}, Elements and RegExps. We888    // would like to return object for those and we can detect an invalid889    // function by making sure that the function object has a call method.890    return 'object';891  }892  return s;893};894895896/**897 * Returns true if the specified value is null.898 * @param {?} val Variable to test.899 * @return {boolean} Whether variable is null.900 */901goog.isNull = function(val) {902  return val === null;903};904905906/**907 * Returns true if the specified value is defined and not null.908 * @param {?} val Variable to test.909 * @return {boolean} Whether variable is defined and not null.910 */911goog.isDefAndNotNull = function(val) {912  // Note that undefined == null.913  return val != null;914};915916917/**918 * Returns true if the specified value is an array.919 * @param {?} val Variable to test.920 * @return {boolean} Whether variable is an array.921 */922goog.isArray = function(val) {923  return goog.typeOf(val) == 'array';924};925926927/**928 * Returns true if the object looks like an array. To qualify as array like929 * the value needs to be either a NodeList or an object with a Number length930 * property.931 * @param {?} val Variable to test.932 * @return {boolean} Whether variable is an array.933 */934goog.isArrayLike = function(val) {935  var type = goog.typeOf(val);936  return type == 'array' || type == 'object' && typeof val.length == 'number';937};938939940/**941 * Returns true if the object looks like a Date. To qualify as Date-like the942 * value needs to be an object and have a getFullYear() function.943 * @param {?} val Variable to test.944 * @return {boolean} Whether variable is a like a Date.945 */946goog.isDateLike = function(val) {947  return goog.isObject(val) && typeof val.getFullYear == 'function';948};949950951/**952 * Returns true if the specified value is a string.953 * @param {?} val Variable to test.954 * @return {boolean} Whether variable is a string.955 */956goog.isString = function(val) {957  return typeof val == 'string';958};959960961/**962 * Returns true if the specified value is a boolean.963 * @param {?} val Variable to test.964 * @return {boolean} Whether variable is boolean.965 */966goog.isBoolean = function(val) {967  return typeof val == 'boolean';968};969970971/**972 * Returns true if the specified value is a number.973 * @param {?} val Variable to test.974 * @return {boolean} Whether variable is a number.975 */976goog.isNumber = function(val) {977  return typeof val == 'number';978};979980981/**982 * Returns true if the specified value is a function.983 * @param {?} val Variable to test.984 * @return {boolean} Whether variable is a function.985 */986goog.isFunction = function(val) {987  return goog.typeOf(val) == 'function';988};989990991/**992 * Returns true if the specified value is an object.  This includes arrays and993 * functions.994 * @param {?} val Variable to test.995 * @return {boolean} Whether variable is an object.996 */997goog.isObject = function(val) {998  var type = typeof val;999  return type == 'object' && val != null || type == 'function';1000  // return Object(val) === val also works, but is slower, especially if val is1001  // not an object.1002};100310041005/**1006 * Gets a unique ID for an object. This mutates the object so that further calls1007 * with the same object as a parameter returns the same value. The unique ID is1008 * guaranteed to be unique across the current session amongst objects that are1009 * passed into {@code getUid}. There is no guarantee that the ID is unique or1010 * consistent across sessions. It is unsafe to generate unique ID for function1011 * prototypes.1012 *1013 * @param {Object} obj The object to get the unique ID for.1014 * @return {number} The unique ID for the object.1015 */1016goog.getUid = function(obj) {1017  // TODO(arv): Make the type stricter, do not accept null.10181019  // In Opera window.hasOwnProperty exists but always returns false so we avoid1020  // using it. As a consequence the unique ID generated for BaseClass.prototype1021  // and SubClass.prototype will be the same.1022  return obj[goog.UID_PROPERTY_] ||1023      (obj[goog.UID_PROPERTY_] = ++goog.uidCounter_);1024};102510261027/**1028 * Whether the given object is alreay assigned a unique ID.1029 *1030 * This does not modify the object.1031 *1032 * @param {Object} obj The object to check.1033 * @return {boolean} Whether there an assigned unique id for the object.1034 */1035goog.hasUid = function(obj) {1036  return !!obj[goog.UID_PROPERTY_];1037};103810391040/**1041 * Removes the unique ID from an object. This is useful if the object was1042 * previously mutated using {@code goog.getUid} in which case the mutation is1043 * undone.1044 * @param {Object} obj The object to remove the unique ID field from.1045 */1046goog.removeUid = function(obj) {1047  // TODO(arv): Make the type stricter, do not accept null.10481049  // In IE, DOM nodes are not instances of Object and throw an exception if we1050  // try to delete.  Instead we try to use removeAttribute.1051  if ('removeAttribute' in obj) {1052    obj.removeAttribute(goog.UID_PROPERTY_);1053  }1054  /** @preserveTry */1055  try {1056    delete obj[goog.UID_PROPERTY_];1057  } catch (ex) {1058  }1059};106010611062/**1063 * Name for unique ID property. Initialized in a way to help avoid collisions1064 * with other closure JavaScript on the same page.1065 * @type {string}1066 * @private1067 */1068goog.UID_PROPERTY_ = 'closure_uid_' + ((Math.random() * 1e9) >>> 0);106910701071/**1072 * Counter for UID.1073 * @type {number}1074 * @private1075 */1076goog.uidCounter_ = 0;107710781079/**1080 * Adds a hash code field to an object. The hash code is unique for the1081 * given object.1082 * @param {Object} obj The object to get the hash code for.1083 * @return {number} The hash code for the object.1084 * @deprecated Use goog.getUid instead.1085 */1086goog.getHashCode = goog.getUid;108710881089/**1090 * Removes the hash code field from an object.1091 * @param {Object} obj The object to remove the field from.1092 * @deprecated Use goog.removeUid instead.1093 */1094goog.removeHashCode = goog.removeUid;109510961097/**1098 * Clones a value. The input may be an Object, Array, or basic type. Objects and1099 * arrays will be cloned recursively.1100 *1101 * WARNINGS:1102 * <code>goog.cloneObject</code> does not detect reference loops. Objects that1103 * refer to themselves will cause infinite recursion.1104 *1105 * <code>goog.cloneObject</code> is unaware of unique identifiers, and copies1106 * UIDs created by <code>getUid</code> into cloned results.1107 *1108 * @param {*} obj The value to clone.1109 * @return {*} A clone of the input value.1110 * @deprecated goog.cloneObject is unsafe. Prefer the goog.object methods.1111 */1112goog.cloneObject = function(obj) {1113  var type = goog.typeOf(obj);1114  if (type == 'object' || type == 'array') {1115    if (obj.clone) {1116      return obj.clone();1117    }1118    var clone = type == 'array' ? [] : {};1119    for (var key in obj) {1120      clone[key] = goog.cloneObject(obj[key]);1121    }1122    return clone;1123  }11241125  return obj;1126};112711281129/**1130 * A native implementation of goog.bind.1131 * @param {Function} fn A function to partially apply.1132 * @param {Object|undefined} selfObj Specifies the object which this should1133 *     point to when the function is run.1134 * @param {...*} var_args Additional arguments that are partially applied to the1135 *     function.1136 * @return {!Function} A partially-applied form of the function bind() was1137 *     invoked as a method of.1138 * @private1139 * @suppress {deprecated} The compiler thinks that Function.prototype.bind is1140 *     deprecated because some people have declared a pure-JS version.1141 *     Only the pure-JS version is truly deprecated.1142 */1143goog.bindNative_ = function(fn, selfObj, var_args) {1144  return /** @type {!Function} */ (fn.call.apply(fn.bind, arguments));1145};114611471148/**1149 * A pure-JS implementation of goog.bind.1150 * @param {Function} fn A function to partially apply.1151 * @param {Object|undefined} selfObj Specifies the object which this should1152 *     point to when the function is run.1153 * @param {...*} var_args Additional arguments that are partially applied to the1154 *     function.1155 * @return {!Function} A partially-applied form of the function bind() was1156 *     invoked as a method of.1157 * @private1158 */1159goog.bindJs_ = function(fn, selfObj, var_args) {1160  if (!fn) {1161    throw new Error();1162  }11631164  if (arguments.length > 2) {1165    var boundArgs = Array.prototype.slice.call(arguments, 2);1166    return function() {1167      // Prepend the bound arguments to the current arguments.1168      var newArgs = Array.prototype.slice.call(arguments);1169      Array.prototype.unshift.apply(newArgs, boundArgs);1170      return fn.apply(selfObj, newArgs);1171    };11721173  } else {1174    return function() {1175      return fn.apply(selfObj, arguments);1176    };1177  }1178};117911801181/**1182 * Partially applies this function to a particular 'this object' and zero or1183 * more arguments. The result is a new function with some arguments of the first1184 * function pre-filled and the value of this 'pre-specified'.1185 *1186 * Remaining arguments specified at call-time are appended to the pre-specified1187 * ones.1188 *1189 * Also see: {@link #partial}.1190 *1191 * Usage:1192 * <pre>var barMethBound = bind(myFunction, myObj, 'arg1', 'arg2');1193 * barMethBound('arg3', 'arg4');</pre>1194 *1195 * @param {?function(this:T, ...)} fn A function to partially apply.1196 * @param {T} selfObj Specifies the object which this should point to when the1197 *     function is run.1198 * @param {...*} var_args Additional arguments that are partially applied to the1199 *     function.1200 * @return {!Function} A partially-applied form of the function bind() was1201 *     invoked as a method of.1202 * @template T1203 * @suppress {deprecated} See above.1204 */1205goog.bind = function(fn, selfObj, var_args) {1206  // TODO(nicksantos): narrow the type signature.1207  if (Function.prototype.bind &&1208      // NOTE(nicksantos): Somebody pulled base.js into the default Chrome1209      // extension environment. This means that for Chrome extensions, they get1210      // the implementation of Function.prototype.bind that calls goog.bind1211      // instead of the native one. Even worse, we don't want to introduce a1212      // circular dependency between goog.bind and Function.prototype.bind, so1213      // we have to hack this to make sure it works correctly.1214      Function.prototype.bind.toString().indexOf('native code') != -1) {1215    goog.bind = goog.bindNative_;1216  } else {1217    goog.bind = goog.bindJs_;1218  }1219  return goog.bind.apply(null, arguments);1220};122112221223/**1224 * Like bind(), except that a 'this object' is not required. Useful when the1225 * target function is already bound.1226 *1227 * Usage:1228 * var g = partial(f, arg1, arg2);1229 * g(arg3, arg4);1230 *1231 * @param {Function} fn A function to partially apply.1232 * @param {...*} var_args Additional arguments that are partially applied to fn.1233 * @return {!Function} A partially-applied form of the function bind() was1234 *     invoked as a method of.1235 */1236goog.partial = function(fn, var_args) {1237  var args = Array.prototype.slice.call(arguments, 1);1238  return function() {1239    // Clone the array (with slice()) and append additional arguments1240    // to the existing arguments.1241    var newArgs = args.slice();1242    newArgs.push.apply(newArgs, arguments);1243    return fn.apply(this, newArgs);1244  };1245};124612471248/**1249 * Copies all the members of a source object to a target object. This method1250 * does not work on all browsers for all objects that contain keys such as1251 * toString or hasOwnProperty. Use goog.object.extend for this purpose.1252 * @param {Object} target Target.1253 * @param {Object} source Source.1254 */1255goog.mixin = function(target, source) {1256  for (var x in source) {1257    target[x] = source[x];1258  }12591260  // For IE7 or lower, the for-in-loop does not contain any properties that are1261  // not enumerable on the prototype object (for example, isPrototypeOf from1262  // Object.prototype) but also it will not include 'replace' on objects that1263  // extend String and change 'replace' (not that it is common for anyone to1264  // extend anything except Object).1265};126612671268/**1269 * @return {number} An integer value representing the number of milliseconds1270 *     between midnight, January 1, 1970 and the current time.1271 */1272goog.now = (goog.TRUSTED_SITE && Date.now) || (function() {1273  // Unary plus operator converts its operand to a number which in the case of1274  // a date is done by calling getTime().1275  return +new Date();1276});127712781279/**1280 * Evals JavaScript in the global scope.  In IE this uses execScript, other1281 * browsers use goog.global.eval. If goog.global.eval does not evaluate in the1282 * global scope (for example, in Safari), appends a script tag instead.1283 * Throws an exception if neither execScript or eval is defined.1284 * @param {string} script JavaScript string.1285 */1286goog.globalEval = function(script) {1287  if (goog.global.execScript) {1288    goog.global.execScript(script, 'JavaScript');1289  } else if (goog.global.eval) {1290    // Test to see if eval works1291    if (goog.evalWorksForGlobals_ == null) {1292      goog.global.eval('var _et_ = 1;');1293      if (typeof goog.global['_et_'] != 'undefined') {1294        delete goog.global['_et_'];1295        goog.evalWorksForGlobals_ = true;1296      } else {1297        goog.evalWorksForGlobals_ = false;1298      }1299    }13001301    if (goog.evalWorksForGlobals_) {1302      goog.global.eval(script);1303    } else {1304      var doc = goog.global.document;1305      var scriptElt = doc.createElement('script');1306      scriptElt.type = 'text/javascript';1307      scriptElt.defer = false;1308      // Note(user): can't use .innerHTML since "t('<test>')" will fail and1309      // .text doesn't work in Safari 2.  Therefore we append a text node.1310      scriptElt.appendChild(doc.createTextNode(script));1311      doc.body.appendChild(scriptElt);1312      doc.body.removeChild(scriptElt);1313    }1314  } else {1315    throw Error('goog.globalEval not available');1316  }1317};131813191320/**1321 * Indicates whether or not we can call 'eval' directly to eval code in the1322 * global scope. Set to a Boolean by the first call to goog.globalEval (which1323 * empirically tests whether eval works for globals). @see goog.globalEval1324 * @type {?boolean}1325 * @private1326 */1327goog.evalWorksForGlobals_ = null;132813291330/**1331 * Optional map of CSS class names to obfuscated names used with1332 * goog.getCssName().1333 * @type {Object|undefined}1334 * @private1335 * @see goog.setCssNameMapping1336 */1337goog.cssNameMapping_;133813391340/**1341 * Optional obfuscation style for CSS class names. Should be set to either1342 * 'BY_WHOLE' or 'BY_PART' if defined.1343 * @type {string|undefined}1344 * @private1345 * @see goog.setCssNameMapping1346 */1347goog.cssNameMappingStyle_;134813491350/**1351 * Handles strings that are intended to be used as CSS class names.1352 *1353 * This function works in tandem with @see goog.setCssNameMapping.1354 *1355 * Without any mapping set, the arguments are simple joined with a hyphen and1356 * passed through unaltered.1357 *1358 * When there is a mapping, there are two possible styles in which these1359 * mappings are used. In the BY_PART style, each part (i.e. in between hyphens)1360 * of the passed in css name is rewritten according to the map. In the BY_WHOLE1361 * style, the full css name is looked up in the map directly. If a rewrite is1362 * not specified by the map, the compiler will output a warning.1363 *1364 * When the mapping is passed to the compiler, it will replace calls to1365 * goog.getCssName with the strings from the mapping, e.g.1366 *     var x = goog.getCssName('foo');1367 *     var y = goog.getCssName(this.baseClass, 'active');1368 *  becomes:1369 *     var x= 'foo';1370 *     var y = this.baseClass + '-active';1371 *1372 * If one argument is passed it will be processed, if two are passed only the1373 * modifier will be processed, as it is assumed the first argument was generated1374 * as a result of calling goog.getCssName.1375 *1376 * @param {string} className The class name.1377 * @param {string=} opt_modifier A modifier to be appended to the class name.1378 * @return {string} The class name or the concatenation of the class name and1379 *     the modifier.1380 */1381goog.getCssName = function(className, opt_modifier) {1382  var getMapping = function(cssName) {1383    return goog.cssNameMapping_[cssName] || cssName;1384  };13851386  var renameByParts = function(cssName) {1387    // Remap all the parts individually.1388    var parts = cssName.split('-');1389    var mapped = [];1390    for (var i = 0; i < parts.length; i++) {1391      mapped.push(getMapping(parts[i]));1392    }1393    return mapped.join('-');1394  };13951396  var rename;1397  if (goog.cssNameMapping_) {1398    rename = goog.cssNameMappingStyle_ == 'BY_WHOLE' ?1399        getMapping : renameByParts;1400  } else {1401    rename = function(a) {1402      return a;1403    };1404  }14051406  if (opt_modifier) {1407    return className + '-' + rename(opt_modifier);1408  } else {1409    return rename(className);1410  }1411};141214131414/**1415 * Sets the map to check when returning a value from goog.getCssName(). Example:1416 * <pre>1417 * goog.setCssNameMapping({1418 *   "goog": "a",1419 *   "disabled": "b",1420 * });1421 *1422 * var x = goog.getCssName('goog');1423 * // The following evaluates to: "a a-b".1424 * goog.getCssName('goog') + ' ' + goog.getCssName(x, 'disabled')1425 * </pre>1426 * When declared as a map of string literals to string literals, the JSCompiler1427 * will replace all calls to goog.getCssName() using the supplied map if the1428 * --closure_pass flag is set.1429 *1430 * @param {!Object} mapping A map of strings to strings where keys are possible1431 *     arguments to goog.getCssName() and values are the corresponding values1432 *     that should be returned.1433 * @param {string=} opt_style The style of css name mapping. There are two valid1434 *     options: 'BY_PART', and 'BY_WHOLE'.1435 * @see goog.getCssName for a description.1436 */1437goog.setCssNameMapping = function(mapping, opt_style) {1438  goog.cssNameMapping_ = mapping;1439  goog.cssNameMappingStyle_ = opt_style;1440};144114421443/**1444 * To use CSS renaming in compiled mode, one of the input files should have a1445 * call to goog.setCssNameMapping() with an object literal that the JSCompiler1446 * can extract and use to replace all calls to goog.getCssName(). In uncompiled1447 * mode, JavaScript code should be loaded before this base.js file that declares1448 * a global variable, CLOSURE_CSS_NAME_MAPPING, which is used below. This is1449 * to ensure that the mapping is loaded before any calls to goog.getCssName()1450 * are made in uncompiled mode.1451 *1452 * A hook for overriding the CSS name mapping.1453 * @type {Object|undefined}1454 */1455goog.global.CLOSURE_CSS_NAME_MAPPING;145614571458if (!COMPILED && goog.global.CLOSURE_CSS_NAME_MAPPING) {1459  // This does not call goog.setCssNameMapping() because the JSCompiler1460  // requires that goog.setCssNameMapping() be called with an object literal.1461  goog.cssNameMapping_ = goog.global.CLOSURE_CSS_NAME_MAPPING;1462}146314641465/**1466 * Gets a localized message.1467 *1468 * This function is a compiler primitive. If you give the compiler a localized1469 * message bundle, it will replace the string at compile-time with a localized1470 * version, and expand goog.getMsg call to a concatenated string.1471 *1472 * Messages must be initialized in the form:1473 * <code>1474 * var MSG_NAME = goog.getMsg('Hello {$placeholder}', {'placeholder': 'world'});1475 * </code>1476 *1477 * @param {string} str Translatable string, places holders in the form {$foo}.1478 * @param {Object=} opt_values Map of place holder name to value.1479 * @return {string} message with placeholders filled.1480 */1481goog.getMsg = function(str, opt_values) {1482  var values = opt_values || {};1483  for (var key in values) {1484    var value = ('' + values[key]).replace(/\$/g, '$$$$');1485    str = str.replace(new RegExp('\\{\\$' + key + '\\}', 'gi'), value);1486  }1487  return str;1488};148914901491/**1492 * Gets a localized message. If the message does not have a translation, gives a1493 * fallback message.1494 *1495 * This is useful when introducing a new message that has not yet been1496 * translated into all languages.1497 *1498 * This function is a compiler primitive. Must be used in the form:1499 * <code>var x = goog.getMsgWithFallback(MSG_A, MSG_B);</code>1500 * where MSG_A and MSG_B were initialized with goog.getMsg.1501 *1502 * @param {string} a The preferred message.1503 * @param {string} b The fallback message.1504 * @return {string} The best translated message.1505 */1506goog.getMsgWithFallback = function(a, b) {1507  return a;1508};150915101511/**1512 * Exposes an unobfuscated global namespace path for the given object.1513 * Note that fields of the exported object *will* be obfuscated, unless they are1514 * exported in turn via this function or goog.exportProperty.1515 *1516 * Also handy for making public items that are defined in anonymous closures.1517 *1518 * ex. goog.exportSymbol('public.path.Foo', Foo);1519 *1520 * ex. goog.exportSymbol('public.path.Foo.staticFunction', Foo.staticFunction);1521 *     public.path.Foo.staticFunction();1522 *1523 * ex. goog.exportSymbol('public.path.Foo.prototype.myMethod',1524 *                       Foo.prototype.myMethod);1525 *     new public.path.Foo().myMethod();1526 *1527 * @param {string} publicPath Unobfuscated name to export.1528 * @param {*} object Object the name should point to.1529 * @param {Object=} opt_objectToExportTo The object to add the path to; default1530 *     is goog.global.1531 */1532goog.exportSymbol = function(publicPath, object, opt_objectToExportTo) {1533  goog.exportPath_(publicPath, object, opt_objectToExportTo);1534};153515361537/**1538 * Exports a property unobfuscated into the object's namespace.1539 * ex. goog.exportProperty(Foo, 'staticFunction', Foo.staticFunction);1540 * ex. goog.exportProperty(Foo.prototype, 'myMethod', Foo.prototype.myMethod);1541 * @param {Object} object Object whose static property is being exported.1542 * @param {string} publicName Unobfuscated name to export.1543 * @param {*} symbol Object the name should point to.1544 */1545goog.exportProperty = function(object, publicName, symbol) {1546  object[publicName] = symbol;1547};154815491550/**1551 * Inherit the prototype methods from one constructor into another.1552 *1553 * Usage:1554 * <pre>1555 * function ParentClass(a, b) { }1556 * ParentClass.prototype.foo = function(a) { }1557 *1558 * function ChildClass(a, b, c) {1559 *   goog.base(this, a, b);1560 * }1561 * goog.inherits(ChildClass, ParentClass);1562 *1563 * var child = new ChildClass('a', 'b', 'see');1564 * child.foo(); // This works.1565 * </pre>1566 *1567 * In addition, a superclass' implementation of a method can be invoked as1568 * follows:1569 *1570 * <pre>1571 * ChildClass.prototype.foo = function(a) {1572 *   ChildClass.superClass_.foo.call(this, a);1573 *   // Other code here.1574 * };1575 * </pre>1576 *1577 * @param {Function} childCtor Child class.1578 * @param {Function} parentCtor Parent class.1579 */1580goog.inherits = function(childCtor, parentCtor) {1581  /** @constructor */1582  function tempCtor() {};1583  tempCtor.prototype = parentCtor.prototype;1584  childCtor.superClass_ = parentCtor.prototype;1585  childCtor.prototype = new tempCtor();1586  /** @override */1587  childCtor.prototype.constructor = childCtor;15881589  /**1590   * Calls superclass constructor/method.1591   *1592   * This function is only available if you use goog.inherits to1593   * express inheritance relationships between classes.1594   *1595   * NOTE: This is a replacement for goog.base and for superClass_1596   * property defined in childCtor.1597   *1598   * @param {!Object} me Should always be "this".1599   * @param {string} methodName The method name to call. Calling1600   *     superclass constructor can be done with the special string1601   *     'constructor'.1602   * @param {...*} var_args The arguments to pass to superclass1603   *     method/constructor.1604   * @return {*} The return value of the superclass method/constructor.1605   */1606  childCtor.base = function(me, methodName, var_args) {1607    var args = Array.prototype.slice.call(arguments, 2);1608    return parentCtor.prototype[methodName].apply(me, args);1609  };1610};161116121613/**1614 * Call up to the superclass.1615 *1616 * If this is called from a constructor, then this calls the superclass1617 * constructor with arguments 1-N.1618 *1619 * If this is called from a prototype method, then you must pass the name of the1620 * method as the second argument to this function. If you do not, you will get a1621 * runtime error. This calls the superclass' method with arguments 2-N.1622 *1623 * This function only works if you use goog.inherits to express inheritance1624 * relationships between your classes.1625 *1626 * This function is a compiler primitive. At compile-time, the compiler will do1627 * macro expansion to remove a lot of the extra overhead that this function1628 * introduces. The compiler will also enforce a lot of the assumptions that this1629 * function makes, and treat it as a compiler error if you break them.1630 *1631 * @param {!Object} me Should always be "this".1632 * @param {*=} opt_methodName The method name if calling a super method.1633 * @param {...*} var_args The rest of the arguments.1634 * @return {*} The return value of the superclass method.1635 * @suppress {es5Strict} This method can not be used in strict mode, but1636 *     all Closure Library consumers must depend on this file.1637 */1638goog.base = function(me, opt_methodName, var_args) {1639  var caller = arguments.callee.caller;16401641  if (goog.STRICT_MODE_COMPATIBLE || (goog.DEBUG && !caller)) {1642    throw Error('arguments.caller not defined.  goog.base() cannot be used ' +1643                'with strict mode code. See ' +1644                'http://www.ecma-international.org/ecma-262/5.1/#sec-C');1645  }16461647  if (caller.superClass_) {1648    // This is a constructor. Call the superclass constructor.1649    return caller.superClass_.constructor.apply(1650        me, Array.prototype.slice.call(arguments, 1));1651  }16521653  var args = Array.prototype.slice.call(arguments, 2);1654  var foundCaller = false;1655  for (var ctor = me.constructor;1656       ctor; ctor = ctor.superClass_ && ctor.superClass_.constructor) {1657    if (ctor.prototype[opt_methodName] === caller) {1658      foundCaller = true;1659    } else if (foundCaller) {1660      return ctor.prototype[opt_methodName].apply(me, args);1661    }1662  }16631664  // If we did not find the caller in the prototype chain, then one of two1665  // things happened:1666  // 1) The caller is an instance method.1667  // 2) This method was not called by the right caller.1668  if (me[opt_methodName] === caller) {1669    return me.constructor.prototype[opt_methodName].apply(me, args);1670  } else {1671    throw Error(1672        'goog.base called from a method of one name ' +1673        'to a method of a different name');1674  }1675};167616771678/**1679 * Allow for aliasing within scope functions.  This function exists for1680 * uncompiled code - in compiled code the calls will be inlined and the aliases1681 * applied.  In uncompiled code the function is simply run since the aliases as1682 * written are valid JavaScript.1683 * @param {function()} fn Function to call.  This function can contain aliases1684 *     to namespaces (e.g. "var dom = goog.dom") or classes1685 *     (e.g. "var Timer = goog.Timer").1686 */1687goog.scope = function(fn) {1688  fn.call(goog.global);1689};169016911692/*1693 * To support uncompiled, strict mode bundles that use eval to divide source1694 * like so:1695 *    eval('someSource;//# sourceUrl sourcefile.js');1696 * We need to export the globally defined symbols "goog" and "COMPILED".1697 * Exporting "goog" breaks the compiler optimizations, so we required that1698 * be defined externally.1699 * NOTE: We don't use goog.exportSymbol here because we don't want to trigger1700 * extern generation when that compiler option is enabled.1701 */1702if (!COMPILED) {1703  goog.global['COMPILED'] = COMPILED;1704}17051706