Home | History | Annotate | Download | only in closure
      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 at
      6 //
      7 //      http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS-IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 /**
     16  * @fileoverview Bootstrap for the Google JS Library (Closure).
     17  *
     18  * In uncompiled mode base.js will write out Closure's deps file, unless the
     19  * global <code>CLOSURE_NO_DEPS</code> is set to true.  This allows projects to
     20  * include their own deps file(s) from different locations.
     21  *
     22  */
     23 
     24 
     25 /**
     26  * @define {boolean} Overridden to true by the compiler when --closure_pass
     27  *     or --mark_as_compiled is specified.
     28  */
     29 var COMPILED = false;
     30 
     31 
     32 /**
     33  * Base namespace for the Closure library.  Checks to see goog is
     34  * already defined in the current scope before assigning to prevent
     35  * clobbering if base.js is loaded more than once.
     36  *
     37  * @const
     38  */
     39 var goog = goog || {}; // Identifies this file as the Closure base.
     40 
     41 
     42 /**
     43  * Reference to the global context.  In most cases this will be 'window'.
     44  */
     45 goog.global = this;
     46 
     47 
     48 /**
     49  * @define {boolean} DEBUG is provided as a convenience so that debugging code
     50  * that should not be included in a production js_binary can be easily stripped
     51  * by specifying --define goog.DEBUG=false to the JSCompiler. For example, most
     52  * toString() methods should be declared inside an "if (goog.DEBUG)" conditional
     53  * because they are generally used for debugging purposes and it is difficult
     54  * for the JSCompiler to statically determine whether they are used.
     55  */
     56 goog.DEBUG = true;
     57 
     58 
     59 /**
     60  * @define {string} LOCALE defines the locale being used for compilation. It is
     61  * used to select locale specific data to be compiled in js binary. BUILD rule
     62  * can specify this value by "--define goog.LOCALE=<locale_name>" as JSCompiler
     63  * option.
     64  *
     65  * Take into account that the locale code format is important. You should use
     66  * the canonical Unicode format with hyphen as a delimiter. Language must be
     67  * lowercase, Language Script - Capitalized, Region - UPPERCASE.
     68  * There are few examples: pt-BR, en, en-US, sr-Latin-BO, zh-Hans-CN.
     69  *
     70  * See more info about locale codes here:
     71  * http://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers
     72  *
     73  * For language codes you should use values defined by ISO 693-1. See it here
     74  * http://www.w3.org/WAI/ER/IG/ert/iso639.htm. There is only one exception from
     75  * this rule: the Hebrew language. For legacy reasons the old code (iw) should
     76  * be used instead of the new code (he), see http://wiki/Main/IIISynonyms.
     77  */
     78 goog.LOCALE = 'en';  // default to en
     79 
     80 
     81 /**
     82  * Creates object stubs for a namespace.  The presence of one or more
     83  * goog.provide() calls indicate that the file defines the given
     84  * objects/namespaces.  Build tools also scan for provide/require statements
     85  * to discern dependencies, build dependency files (see deps.js), etc.
     86  * @see goog.require
     87  * @param {string} name Namespace provided by this file in the form
     88  *     "goog.package.part".
     89  */
     90 goog.provide = function(name) {
     91   if (!COMPILED) {
     92     // Ensure that the same namespace isn't provided twice. This is intended
     93     // to teach new developers that 'goog.provide' is effectively a variable
     94     // declaration. And when JSCompiler transforms goog.provide into a real
     95     // variable declaration, the compiled JS should work the same as the raw
     96     // JS--even when the raw JS uses goog.provide incorrectly.
     97     if (goog.isProvided_(name)) {
     98       throw Error('Namespace "' + name + '" already declared.');
     99     }
    100     delete goog.implicitNamespaces_[name];
    101 
    102     var namespace = name;
    103     while ((namespace = namespace.substring(0, namespace.lastIndexOf('.')))) {
    104       if (goog.getObjectByName(namespace)) {
    105         break;
    106       }
    107       goog.implicitNamespaces_[namespace] = true;
    108     }
    109   }
    110 
    111   goog.exportPath_(name);
    112 };
    113 
    114 
    115 /**
    116  * Marks that the current file should only be used for testing, and never for
    117  * live code in production.
    118  * @param {string=} opt_message Optional message to add to the error that's
    119  *     raised when used in production code.
    120  */
    121 goog.setTestOnly = function(opt_message) {
    122   if (COMPILED && !goog.DEBUG) {
    123     opt_message = opt_message || '';
    124     throw Error('Importing test-only code into non-debug environment' +
    125                 opt_message ? ': ' + opt_message : '.');
    126   }
    127 };
    128 
    129 
    130 if (!COMPILED) {
    131 
    132   /**
    133    * Check if the given name has been goog.provided. This will return false for
    134    * names that are available only as implicit namespaces.
    135    * @param {string} name name of the object to look for.
    136    * @return {boolean} Whether the name has been provided.
    137    * @private
    138    */
    139   goog.isProvided_ = function(name) {
    140     return !goog.implicitNamespaces_[name] && !!goog.getObjectByName(name);
    141   };
    142 
    143   /**
    144    * Namespaces implicitly defined by goog.provide. For example,
    145    * goog.provide('goog.events.Event') implicitly declares
    146    * that 'goog' and 'goog.events' must be namespaces.
    147    *
    148    * @type {Object}
    149    * @private
    150    */
    151   goog.implicitNamespaces_ = {};
    152 }
    153 
    154 
    155 /**
    156  * Builds an object structure for the provided namespace path,
    157  * ensuring that names that already exist are not overwritten. For
    158  * example:
    159  * "a.b.c" -> a = {};a.b={};a.b.c={};
    160  * Used by goog.provide and goog.exportSymbol.
    161  * @param {string} name name of the object that this file defines.
    162  * @param {*=} opt_object the object to expose at the end of the path.
    163  * @param {Object=} opt_objectToExportTo The object to add the path to; default
    164  *     is |goog.global|.
    165  * @private
    166  */
    167 goog.exportPath_ = function(name, opt_object, opt_objectToExportTo) {
    168   var parts = name.split('.');
    169   var cur = opt_objectToExportTo || goog.global;
    170 
    171   // Internet Explorer exhibits strange behavior when throwing errors from
    172   // methods externed in this manner.  See the testExportSymbolExceptions in
    173   // base_test.html for an example.
    174   if (!(parts[0] in cur) && cur.execScript) {
    175     cur.execScript('var ' + parts[0]);
    176   }
    177 
    178   // Certain browsers cannot parse code in the form for((a in b); c;);
    179   // This pattern is produced by the JSCompiler when it collapses the
    180   // statement above into the conditional loop below. To prevent this from
    181   // happening, use a for-loop and reserve the init logic as below.
    182 
    183   // Parentheses added to eliminate strict JS warning in Firefox.
    184   for (var part; parts.length && (part = parts.shift());) {
    185     if (!parts.length && goog.isDef(opt_object)) {
    186       // last part and we have an object; use it
    187       cur[part] = opt_object;
    188     } else if (cur[part]) {
    189       cur = cur[part];
    190     } else {
    191       cur = cur[part] = {};
    192     }
    193   }
    194 };
    195 
    196 
    197 /**
    198  * Returns an object based on its fully qualified external name.  If you are
    199  * using a compilation pass that renames property names beware that using this
    200  * function will not find renamed properties.
    201  *
    202  * @param {string} name The fully qualified name.
    203  * @param {Object=} opt_obj The object within which to look; default is
    204  *     |goog.global|.
    205  * @return {Object} The object or, if not found, null.
    206  */
    207 goog.getObjectByName = function(name, opt_obj) {
    208   var parts = name.split('.');
    209   var cur = opt_obj || goog.global;
    210   for (var part; part = parts.shift(); ) {
    211     if (goog.isDefAndNotNull(cur[part])) {
    212       cur = cur[part];
    213     } else {
    214       return null;
    215     }
    216   }
    217   return cur;
    218 };
    219 
    220 
    221 /**
    222  * Globalizes a whole namespace, such as goog or goog.lang.
    223  *
    224  * @param {Object} obj The namespace to globalize.
    225  * @param {Object=} opt_global The object to add the properties to.
    226  * @deprecated Properties may be explicitly exported to the global scope, but
    227  *     this should no longer be done in bulk.
    228  */
    229 goog.globalize = function(obj, opt_global) {
    230   var global = opt_global || goog.global;
    231   for (var x in obj) {
    232     global[x] = obj[x];
    233   }
    234 };
    235 
    236 
    237 /**
    238  * Adds a dependency from a file to the files it requires.
    239  * @param {string} relPath The path to the js file.
    240  * @param {Array} provides An array of strings with the names of the objects
    241  *                         this file provides.
    242  * @param {Array} requires An array of strings with the names of the objects
    243  *                         this file requires.
    244  */
    245 goog.addDependency = function(relPath, provides, requires) {
    246   if (!COMPILED) {
    247     var provide, require;
    248     var path = relPath.replace(/\\/g, '/');
    249     var deps = goog.dependencies_;
    250     for (var i = 0; provide = provides[i]; i++) {
    251       deps.nameToPath[provide] = path;
    252       if (!(path in deps.pathToNames)) {
    253         deps.pathToNames[path] = {};
    254       }
    255       deps.pathToNames[path][provide] = true;
    256     }
    257     for (var j = 0; require = requires[j]; j++) {
    258       if (!(path in deps.requires)) {
    259         deps.requires[path] = {};
    260       }
    261       deps.requires[path][require] = true;
    262     }
    263   }
    264 };
    265 
    266 
    267 
    268 
    269 // NOTE(user): The debug DOM loader was included in base.js as an orignal
    270 // way to do "debug-mode" development.  The dependency system can sometimes
    271 // be confusing, as can the debug DOM loader's asyncronous nature.
    272 //
    273 // With the DOM loader, a call to goog.require() is not blocking -- the
    274 // script will not load until some point after the current script.  If a
    275 // namespace is needed at runtime, it needs to be defined in a previous
    276 // script, or loaded via require() with its registered dependencies.
    277 // User-defined namespaces may need their own deps file.  See http://go/js_deps,
    278 // http://go/genjsdeps, or, externally, DepsWriter.
    279 // http://code.google.com/closure/library/docs/depswriter.html
    280 //
    281 // Because of legacy clients, the DOM loader can't be easily removed from
    282 // base.js.  Work is being done to make it disableable or replaceable for
    283 // different environments (DOM-less JavaScript interpreters like Rhino or V8,
    284 // for example). See bootstrap/ for more information.
    285 
    286 
    287 /**
    288  * @define {boolean} Whether to enable the debug loader.
    289  *
    290  * If enabled, a call to goog.require() will attempt to load the namespace by
    291  * appending a script tag to the DOM (if the namespace has been registered).
    292  *
    293  * If disabled, goog.require() will simply assert that the namespace has been
    294  * provided (and depend on the fact that some outside tool correctly ordered
    295  * the script).
    296  */
    297 goog.ENABLE_DEBUG_LOADER = true;
    298 
    299 
    300 /**
    301  * Implements a system for the dynamic resolution of dependencies
    302  * that works in parallel with the BUILD system. Note that all calls
    303  * to goog.require will be stripped by the JSCompiler when the
    304  * --closure_pass option is used.
    305  * @see goog.provide
    306  * @param {string} name Namespace to include (as was given in goog.provide())
    307  *     in the form "goog.package.part".
    308  */
    309 goog.require = function(name) {
    310 
    311   // if the object already exists we do not need do do anything
    312   // TODO(user): If we start to support require based on file name this has
    313   //            to change
    314   // TODO(user): If we allow goog.foo.* this has to change
    315   // TODO(user): If we implement dynamic load after page load we should probably
    316   //            not remove this code for the compiled output
    317   if (!COMPILED) {
    318     if (goog.isProvided_(name)) {
    319       return;
    320     }
    321 
    322     if (goog.ENABLE_DEBUG_LOADER) {
    323       var path = goog.getPathFromDeps_(name);
    324       if (path) {
    325         goog.included_[path] = true;
    326         goog.writeScripts_();
    327         return;
    328       }
    329     }
    330 
    331     var errorMessage = 'goog.require could not find: ' + name;
    332     if (goog.global.console) {
    333       goog.global.console['error'](errorMessage);
    334     }
    335 
    336 
    337       throw Error(errorMessage);
    338 
    339   }
    340 };
    341 
    342 
    343 /**
    344  * Path for included scripts
    345  * @type {string}
    346  */
    347 goog.basePath = '';
    348 
    349 
    350 /**
    351  * A hook for overriding the base path.
    352  * @type {string|undefined}
    353  */
    354 goog.global.CLOSURE_BASE_PATH;
    355 
    356 
    357 /**
    358  * Whether to write out Closure's deps file. By default,
    359  * the deps are written.
    360  * @type {boolean|undefined}
    361  */
    362 goog.global.CLOSURE_NO_DEPS;
    363 
    364 
    365 /**
    366  * A function to import a single script. This is meant to be overridden when
    367  * Closure is being run in non-HTML contexts, such as web workers. It's defined
    368  * in the global scope so that it can be set before base.js is loaded, which
    369  * allows deps.js to be imported properly.
    370  *
    371  * The function is passed the script source, which is a relative URI. It should
    372  * return true if the script was imported, false otherwise.
    373  */
    374 goog.global.CLOSURE_IMPORT_SCRIPT;
    375 
    376 
    377 /**
    378  * Null function used for default values of callbacks, etc.
    379  * @return {void} Nothing.
    380  */
    381 goog.nullFunction = function() {};
    382 
    383 
    384 /**
    385  * The identity function. Returns its first argument.
    386  *
    387  * @param {...*} var_args The arguments of the function.
    388  * @return {*} The first argument.
    389  * @deprecated Use goog.functions.identity instead.
    390  */
    391 goog.identityFunction = function(var_args) {
    392   return arguments[0];
    393 };
    394 
    395 
    396 /**
    397  * When defining a class Foo with an abstract method bar(), you can do:
    398  *
    399  * Foo.prototype.bar = goog.abstractMethod
    400  *
    401  * Now if a subclass of Foo fails to override bar(), an error
    402  * will be thrown when bar() is invoked.
    403  *
    404  * Note: This does not take the name of the function to override as
    405  * an argument because that would make it more difficult to obfuscate
    406  * our JavaScript code.
    407  *
    408  * @type {!Function}
    409  * @throws {Error} when invoked to indicate the method should be
    410  *   overridden.
    411  */
    412 goog.abstractMethod = function() {
    413   throw Error('unimplemented abstract method');
    414 };
    415 
    416 
    417 /**
    418  * Adds a {@code getInstance} static method that always return the same instance
    419  * object.
    420  * @param {!Function} ctor The constructor for the class to add the static
    421  *     method to.
    422  */
    423 goog.addSingletonGetter = function(ctor) {
    424   ctor.getInstance = function() {
    425     return ctor.instance_ || (ctor.instance_ = new ctor());
    426   };
    427 };
    428 
    429 
    430 if (!COMPILED && goog.ENABLE_DEBUG_LOADER) {
    431   /**
    432    * Object used to keep track of urls that have already been added. This
    433    * record allows the prevention of circular dependencies.
    434    * @type {Object}
    435    * @private
    436    */
    437   goog.included_ = {};
    438 
    439 
    440   /**
    441    * This object is used to keep track of dependencies and other data that is
    442    * used for loading scripts
    443    * @private
    444    * @type {Object}
    445    */
    446   goog.dependencies_ = {
    447     pathToNames: {}, // 1 to many
    448     nameToPath: {}, // 1 to 1
    449     requires: {}, // 1 to many
    450     // used when resolving dependencies to prevent us from
    451     // visiting the file twice
    452     visited: {},
    453     written: {} // used to keep track of script files we have written
    454   };
    455 
    456 
    457   /**
    458    * Tries to detect whether is in the context of an HTML document.
    459    * @return {boolean} True if it looks like HTML document.
    460    * @private
    461    */
    462   goog.inHtmlDocument_ = function() {
    463     var doc = goog.global.document;
    464     return typeof doc != 'undefined' &&
    465            'write' in doc;  // XULDocument misses write.
    466   };
    467 
    468 
    469   /**
    470    * Tries to detect the base path of the base.js script that bootstraps Closure
    471    * @private
    472    */
    473   goog.findBasePath_ = function() {
    474     if (goog.global.CLOSURE_BASE_PATH) {
    475       goog.basePath = goog.global.CLOSURE_BASE_PATH;
    476       return;
    477     } else if (!goog.inHtmlDocument_()) {
    478       return;
    479     }
    480     var doc = goog.global.document;
    481     var scripts = doc.getElementsByTagName('script');
    482     // Search backwards since the current script is in almost all cases the one
    483     // that has base.js.
    484     for (var i = scripts.length - 1; i >= 0; --i) {
    485       var src = scripts[i].src;
    486       var qmark = src.lastIndexOf('?');
    487       var l = qmark == -1 ? src.length : qmark;
    488       if (src.substr(l - 7, 7) == 'base.js') {
    489         goog.basePath = src.substr(0, l - 7);
    490         return;
    491       }
    492     }
    493   };
    494 
    495 
    496   /**
    497    * Imports a script if, and only if, that script hasn't already been imported.
    498    * (Must be called at execution time)
    499    * @param {string} src Script source.
    500    * @private
    501    */
    502   goog.importScript_ = function(src) {
    503     var importScript = goog.global.CLOSURE_IMPORT_SCRIPT ||
    504         goog.writeScriptTag_;
    505     if (!goog.dependencies_.written[src] && importScript(src)) {
    506       goog.dependencies_.written[src] = true;
    507     }
    508   };
    509 
    510 
    511   /**
    512    * The default implementation of the import function. Writes a script tag to
    513    * import the script.
    514    *
    515    * @param {string} src The script source.
    516    * @return {boolean} True if the script was imported, false otherwise.
    517    * @private
    518    */
    519   goog.writeScriptTag_ = function(src) {
    520     if (goog.inHtmlDocument_()) {
    521       var doc = goog.global.document;
    522       doc.write(
    523           '<script type="text/javascript" src="' + src + '"></' + 'script>');
    524       return true;
    525     } else {
    526       return false;
    527     }
    528   };
    529 
    530 
    531   /**
    532    * Resolves dependencies based on the dependencies added using addDependency
    533    * and calls importScript_ in the correct order.
    534    * @private
    535    */
    536   goog.writeScripts_ = function() {
    537     // the scripts we need to write this time
    538     var scripts = [];
    539     var seenScript = {};
    540     var deps = goog.dependencies_;
    541 
    542     function visitNode(path) {
    543       if (path in deps.written) {
    544         return;
    545       }
    546 
    547       // we have already visited this one. We can get here if we have cyclic
    548       // dependencies
    549       if (path in deps.visited) {
    550         if (!(path in seenScript)) {
    551           seenScript[path] = true;
    552           scripts.push(path);
    553         }
    554         return;
    555       }
    556 
    557       deps.visited[path] = true;
    558 
    559       if (path in deps.requires) {
    560         for (var requireName in deps.requires[path]) {
    561           // If the required name is defined, we assume that it was already
    562           // bootstrapped by other means.
    563           if (!goog.isProvided_(requireName)) {
    564             if (requireName in deps.nameToPath) {
    565               visitNode(deps.nameToPath[requireName]);
    566             } else {
    567               throw Error('Undefined nameToPath for ' + requireName);
    568             }
    569           }
    570         }
    571       }
    572 
    573       if (!(path in seenScript)) {
    574         seenScript[path] = true;
    575         scripts.push(path);
    576       }
    577     }
    578 
    579     for (var path in goog.included_) {
    580       if (!deps.written[path]) {
    581         visitNode(path);
    582       }
    583     }
    584 
    585     for (var i = 0; i < scripts.length; i++) {
    586       if (scripts[i]) {
    587         goog.importScript_(goog.basePath + scripts[i]);
    588       } else {
    589         throw Error('Undefined script input');
    590       }
    591     }
    592   };
    593 
    594 
    595   /**
    596    * Looks at the dependency rules and tries to determine the script file that
    597    * fulfills a particular rule.
    598    * @param {string} rule In the form goog.namespace.Class or project.script.
    599    * @return {?string} Url corresponding to the rule, or null.
    600    * @private
    601    */
    602   goog.getPathFromDeps_ = function(rule) {
    603     if (rule in goog.dependencies_.nameToPath) {
    604       return goog.dependencies_.nameToPath[rule];
    605     } else {
    606       return null;
    607     }
    608   };
    609 
    610   goog.findBasePath_();
    611 
    612   // Allow projects to manage the deps files themselves.
    613   if (!goog.global.CLOSURE_NO_DEPS) {
    614     goog.importScript_(goog.basePath + 'deps.js');
    615   }
    616 }
    617 
    618 
    619 
    620 //==============================================================================
    621 // Language Enhancements
    622 //==============================================================================
    623 
    624 
    625 /**
    626  * This is a "fixed" version of the typeof operator.  It differs from the typeof
    627  * operator in such a way that null returns 'null' and arrays return 'array'.
    628  * @param {*} value The value to get the type of.
    629  * @return {string} The name of the type.
    630  */
    631 goog.typeOf = function(value) {
    632   var s = typeof value;
    633   if (s == 'object') {
    634     if (value) {
    635       // Check these first, so we can avoid calling Object.prototype.toString if
    636       // possible.
    637       //
    638       // IE improperly marshals tyepof across execution contexts, but a
    639       // cross-context object will still return false for "instanceof Object".
    640       if (value instanceof Array) {
    641         return 'array';
    642       } else if (value instanceof Object) {
    643         return s;
    644       }
    645 
    646       // HACK: In order to use an Object prototype method on the arbitrary
    647       //   value, the compiler requires the value be cast to type Object,
    648       //   even though the ECMA spec explicitly allows it.
    649       var className = Object.prototype.toString.call(
    650           /** @type {Object} */ (value));
    651       // In Firefox 3.6, attempting to access iframe window objects' length
    652       // property throws an NS_ERROR_FAILURE, so we need to special-case it
    653       // here.
    654       if (className == '[object Window]') {
    655         return 'object';
    656       }
    657 
    658       // We cannot always use constructor == Array or instanceof Array because
    659       // different frames have different Array objects. In IE6, if the iframe
    660       // where the array was created is destroyed, the array loses its
    661       // prototype. Then dereferencing val.splice here throws an exception, so
    662       // we can't use goog.isFunction. Calling typeof directly returns 'unknown'
    663       // so that will work. In this case, this function will return false and
    664       // most array functions will still work because the array is still
    665       // array-like (supports length and []) even though it has lost its
    666       // prototype.
    667       // Mark Miller noticed that Object.prototype.toString
    668       // allows access to the unforgeable [[Class]] property.
    669       //  15.2.4.2 Object.prototype.toString ( )
    670       //  When the toString method is called, the following steps are taken:
    671       //      1. Get the [[Class]] property of this object.
    672       //      2. Compute a string value by concatenating the three strings
    673       //         "[object ", Result(1), and "]".
    674       //      3. Return Result(2).
    675       // and this behavior survives the destruction of the execution context.
    676       if ((className == '[object Array]' ||
    677            // In IE all non value types are wrapped as objects across window
    678            // boundaries (not iframe though) so we have to do object detection
    679            // for this edge case
    680            typeof value.length == 'number' &&
    681            typeof value.splice != 'undefined' &&
    682            typeof value.propertyIsEnumerable != 'undefined' &&
    683            !value.propertyIsEnumerable('splice')
    684 
    685           )) {
    686         return 'array';
    687       }
    688       // HACK: There is still an array case that fails.
    689       //     function ArrayImpostor() {}
    690       //     ArrayImpostor.prototype = [];
    691       //     var impostor = new ArrayImpostor;
    692       // this can be fixed by getting rid of the fast path
    693       // (value instanceof Array) and solely relying on
    694       // (value && Object.prototype.toString.vall(value) === '[object Array]')
    695       // but that would require many more function calls and is not warranted
    696       // unless closure code is receiving objects from untrusted sources.
    697 
    698       // IE in cross-window calls does not correctly marshal the function type
    699       // (it appears just as an object) so we cannot use just typeof val ==
    700       // 'function'. However, if the object has a call property, it is a
    701       // function.
    702       if ((className == '[object Function]' ||
    703           typeof value.call != 'undefined' &&
    704           typeof value.propertyIsEnumerable != 'undefined' &&
    705           !value.propertyIsEnumerable('call'))) {
    706         return 'function';
    707       }
    708 
    709 
    710     } else {
    711       return 'null';
    712     }
    713 
    714   } else if (s == 'function' && typeof value.call == 'undefined') {
    715     // In Safari typeof nodeList returns 'function', and on Firefox
    716     // typeof behaves similarly for HTML{Applet,Embed,Object}Elements
    717     // and RegExps.  We would like to return object for those and we can
    718     // detect an invalid function by making sure that the function
    719     // object has a call method.
    720     return 'object';
    721   }
    722   return s;
    723 };
    724 
    725 
    726 /**
    727  * Safe way to test whether a property is enumarable.  It allows testing
    728  * for enumerable on objects where 'propertyIsEnumerable' is overridden or
    729  * does not exist (like DOM nodes in IE). Does not use browser native
    730  * Object.propertyIsEnumerable.
    731  * @param {Object} object The object to test if the property is enumerable.
    732  * @param {string} propName The property name to check for.
    733  * @return {boolean} True if the property is enumarable.
    734  * @private
    735  */
    736 goog.propertyIsEnumerableCustom_ = function(object, propName) {
    737   // KJS in Safari 2 is not ECMAScript compatible and lacks crucial methods
    738   // such as propertyIsEnumerable.  We therefore use a workaround.
    739   // Does anyone know a more efficient work around?
    740   if (propName in object) {
    741     for (var key in object) {
    742       if (key == propName &&
    743           Object.prototype.hasOwnProperty.call(object, propName)) {
    744         return true;
    745       }
    746     }
    747   }
    748   return false;
    749 };
    750 
    751 
    752 /**
    753  * Safe way to test whether a property is enumarable.  It allows testing
    754  * for enumerable on objects where 'propertyIsEnumerable' is overridden or
    755  * does not exist (like DOM nodes in IE).
    756  * @param {Object} object The object to test if the property is enumerable.
    757  * @param {string} propName The property name to check for.
    758  * @return {boolean} True if the property is enumarable.
    759  * @private
    760  */
    761 goog.propertyIsEnumerable_ = function(object, propName) {
    762   // In IE if object is from another window, cannot use propertyIsEnumerable
    763   // from this window's Object. Will raise a 'JScript object expected' error.
    764   if (object instanceof Object) {
    765     return Object.prototype.propertyIsEnumerable.call(object, propName);
    766   } else {
    767     return goog.propertyIsEnumerableCustom_(object, propName);
    768   }
    769 };
    770 
    771 
    772 /**
    773  * Returns true if the specified value is not |undefined|.
    774  * WARNING: Do not use this to test if an object has a property. Use the in
    775  * operator instead.  Additionally, this function assumes that the global
    776  * undefined variable has not been redefined.
    777  * @param {*} val Variable to test.
    778  * @return {boolean} Whether variable is defined.
    779  */
    780 goog.isDef = function(val) {
    781   return val !== undefined;
    782 };
    783 
    784 
    785 /**
    786  * Returns true if the specified value is |null|
    787  * @param {*} val Variable to test.
    788  * @return {boolean} Whether variable is null.
    789  */
    790 goog.isNull = function(val) {
    791   return val === null;
    792 };
    793 
    794 
    795 /**
    796  * Returns true if the specified value is defined and not null
    797  * @param {*} val Variable to test.
    798  * @return {boolean} Whether variable is defined and not null.
    799  */
    800 goog.isDefAndNotNull = function(val) {
    801   // Note that undefined == null.
    802   return val != null;
    803 };
    804 
    805 
    806 /**
    807  * Returns true if the specified value is an array
    808  * @param {*} val Variable to test.
    809  * @return {boolean} Whether variable is an array.
    810  */
    811 goog.isArray = function(val) {
    812   return goog.typeOf(val) == 'array';
    813 };
    814 
    815 
    816 /**
    817  * Returns true if the object looks like an array. To qualify as array like
    818  * the value needs to be either a NodeList or an object with a Number length
    819  * property.
    820  * @param {*} val Variable to test.
    821  * @return {boolean} Whether variable is an array.
    822  */
    823 goog.isArrayLike = function(val) {
    824   var type = goog.typeOf(val);
    825   return type == 'array' || type == 'object' && typeof val.length == 'number';
    826 };
    827 
    828 
    829 /**
    830  * Returns true if the object looks like a Date. To qualify as Date-like
    831  * the value needs to be an object and have a getFullYear() function.
    832  * @param {*} val Variable to test.
    833  * @return {boolean} Whether variable is a like a Date.
    834  */
    835 goog.isDateLike = function(val) {
    836   return goog.isObject(val) && typeof val.getFullYear == 'function';
    837 };
    838 
    839 
    840 /**
    841  * Returns true if the specified value is a string
    842  * @param {*} val Variable to test.
    843  * @return {boolean} Whether variable is a string.
    844  */
    845 goog.isString = function(val) {
    846   return typeof val == 'string';
    847 };
    848 
    849 
    850 /**
    851  * Returns true if the specified value is a boolean
    852  * @param {*} val Variable to test.
    853  * @return {boolean} Whether variable is boolean.
    854  */
    855 goog.isBoolean = function(val) {
    856   return typeof val == 'boolean';
    857 };
    858 
    859 
    860 /**
    861  * Returns true if the specified value is a number
    862  * @param {*} val Variable to test.
    863  * @return {boolean} Whether variable is a number.
    864  */
    865 goog.isNumber = function(val) {
    866   return typeof val == 'number';
    867 };
    868 
    869 
    870 /**
    871  * Returns true if the specified value is a function
    872  * @param {*} val Variable to test.
    873  * @return {boolean} Whether variable is a function.
    874  */
    875 goog.isFunction = function(val) {
    876   return goog.typeOf(val) == 'function';
    877 };
    878 
    879 
    880 /**
    881  * Returns true if the specified value is an object.  This includes arrays
    882  * and functions.
    883  * @param {*} val Variable to test.
    884  * @return {boolean} Whether variable is an object.
    885  */
    886 goog.isObject = function(val) {
    887   var type = goog.typeOf(val);
    888   return type == 'object' || type == 'array' || type == 'function';
    889 };
    890 
    891 
    892 /**
    893  * Gets a unique ID for an object. This mutates the object so that further
    894  * calls with the same object as a parameter returns the same value. The unique
    895  * ID is guaranteed to be unique across the current session amongst objects that
    896  * are passed into {@code getUid}. There is no guarantee that the ID is unique
    897  * or consistent across sessions. It is unsafe to generate unique ID for
    898  * function prototypes.
    899  *
    900  * @param {Object} obj The object to get the unique ID for.
    901  * @return {number} The unique ID for the object.
    902  */
    903 goog.getUid = function(obj) {
    904   // TODO(user): Make the type stricter, do not accept null.
    905 
    906   // In Opera window.hasOwnProperty exists but always returns false so we avoid
    907   // using it. As a consequence the unique ID generated for BaseClass.prototype
    908   // and SubClass.prototype will be the same.
    909   return obj[goog.UID_PROPERTY_] ||
    910       (obj[goog.UID_PROPERTY_] = ++goog.uidCounter_);
    911 };
    912 
    913 
    914 /**
    915  * Removes the unique ID from an object. This is useful if the object was
    916  * previously mutated using {@code goog.getUid} in which case the mutation is
    917  * undone.
    918  * @param {Object} obj The object to remove the unique ID field from.
    919  */
    920 goog.removeUid = function(obj) {
    921   // TODO(user): Make the type stricter, do not accept null.
    922 
    923   // DOM nodes in IE are not instance of Object and throws exception
    924   // for delete. Instead we try to use removeAttribute
    925   if ('removeAttribute' in obj) {
    926     obj.removeAttribute(goog.UID_PROPERTY_);
    927   }
    928   /** @preserveTry */
    929   try {
    930     delete obj[goog.UID_PROPERTY_];
    931   } catch (ex) {
    932   }
    933 };
    934 
    935 
    936 /**
    937  * Name for unique ID property. Initialized in a way to help avoid collisions
    938  * with other closure javascript on the same page.
    939  * @type {string}
    940  * @private
    941  */
    942 goog.UID_PROPERTY_ = 'closure_uid_' +
    943     Math.floor(Math.random() * 2147483648).toString(36);
    944 
    945 
    946 /**
    947  * Counter for UID.
    948  * @type {number}
    949  * @private
    950  */
    951 goog.uidCounter_ = 0;
    952 
    953 
    954 /**
    955  * Adds a hash code field to an object. The hash code is unique for the
    956  * given object.
    957  * @param {Object} obj The object to get the hash code for.
    958  * @return {number} The hash code for the object.
    959  * @deprecated Use goog.getUid instead.
    960  */
    961 goog.getHashCode = goog.getUid;
    962 
    963 
    964 /**
    965  * Removes the hash code field from an object.
    966  * @param {Object} obj The object to remove the field from.
    967  * @deprecated Use goog.removeUid instead.
    968  */
    969 goog.removeHashCode = goog.removeUid;
    970 
    971 
    972 /**
    973  * Clones a value. The input may be an Object, Array, or basic type. Objects and
    974  * arrays will be cloned recursively.
    975  *
    976  * WARNINGS:
    977  * <code>goog.cloneObject</code> does not detect reference loops. Objects that
    978  * refer to themselves will cause infinite recursion.
    979  *
    980  * <code>goog.cloneObject</code> is unaware of unique identifiers, and copies
    981  * UIDs created by <code>getUid</code> into cloned results.
    982  *
    983  * @param {*} obj The value to clone.
    984  * @return {*} A clone of the input value.
    985  * @deprecated goog.cloneObject is unsafe. Prefer the goog.object methods.
    986  */
    987 goog.cloneObject = function(obj) {
    988   var type = goog.typeOf(obj);
    989   if (type == 'object' || type == 'array') {
    990     if (obj.clone) {
    991       return obj.clone();
    992     }
    993     var clone = type == 'array' ? [] : {};
    994     for (var key in obj) {
    995       clone[key] = goog.cloneObject(obj[key]);
    996     }
    997     return clone;
    998   }
    999 
   1000   return obj;
   1001 };
   1002 
   1003 
   1004 /**
   1005  * Forward declaration for the clone method. This is necessary until the
   1006  * compiler can better support duck-typing constructs as used in
   1007  * goog.cloneObject.
   1008  *
   1009  * TODO(user): Remove once the JSCompiler can infer that the check for
   1010  * proto.clone is safe in goog.cloneObject.
   1011  *
   1012  * @type {Function}
   1013  */
   1014 Object.prototype.clone;
   1015 
   1016 
   1017 /**
   1018  * A native implementation of goog.bind.
   1019  * @param {Function} fn A function to partially apply.
   1020  * @param {Object|undefined} selfObj Specifies the object which |this| should
   1021  *     point to when the function is run. If the value is null or undefined, it
   1022  *     will default to the global object.
   1023  * @param {...*} var_args Additional arguments that are partially
   1024  *     applied to the function.
   1025  * @return {!Function} A partially-applied form of the function bind() was
   1026  *     invoked as a method of.
   1027  * @private
   1028  * @suppress {deprecated} The compiler thinks that Function.prototype.bind
   1029  *     is deprecated because some people have declared a pure-JS version.
   1030  *     Only the pure-JS version is truly deprecated.
   1031  */
   1032 goog.bindNative_ = function(fn, selfObj, var_args) {
   1033   return /** @type {!Function} */ (fn.call.apply(fn.bind, arguments));
   1034 };
   1035 
   1036 
   1037 /**
   1038  * A pure-JS implementation of goog.bind.
   1039  * @param {Function} fn A function to partially apply.
   1040  * @param {Object|undefined} selfObj Specifies the object which |this| should
   1041  *     point to when the function is run. If the value is null or undefined, it
   1042  *     will default to the global object.
   1043  * @param {...*} var_args Additional arguments that are partially
   1044  *     applied to the function.
   1045  * @return {!Function} A partially-applied form of the function bind() was
   1046  *     invoked as a method of.
   1047  * @private
   1048  */
   1049 goog.bindJs_ = function(fn, selfObj, var_args) {
   1050   var context = selfObj || goog.global;
   1051 
   1052   if (arguments.length > 2) {
   1053     var boundArgs = Array.prototype.slice.call(arguments, 2);
   1054     return function() {
   1055       // Prepend the bound arguments to the current arguments.
   1056       var newArgs = Array.prototype.slice.call(arguments);
   1057       Array.prototype.unshift.apply(newArgs, boundArgs);
   1058       return fn.apply(context, newArgs);
   1059     };
   1060 
   1061   } else {
   1062     return function() {
   1063       return fn.apply(context, arguments);
   1064     };
   1065   }
   1066 };
   1067 
   1068 
   1069 /**
   1070  * Partially applies this function to a particular 'this object' and zero or
   1071  * more arguments. The result is a new function with some arguments of the first
   1072  * function pre-filled and the value of |this| 'pre-specified'.<br><br>
   1073  *
   1074  * Remaining arguments specified at call-time are appended to the pre-
   1075  * specified ones.<br><br>
   1076  *
   1077  * Also see: {@link #partial}.<br><br>
   1078  *
   1079  * Usage:
   1080  * <pre>var barMethBound = bind(myFunction, myObj, 'arg1', 'arg2');
   1081  * barMethBound('arg3', 'arg4');</pre>
   1082  *
   1083  * @param {Function} fn A function to partially apply.
   1084  * @param {Object|undefined} selfObj Specifies the object which |this| should
   1085  *     point to when the function is run. If the value is null or undefined, it
   1086  *     will default to the global object.
   1087  * @param {...*} var_args Additional arguments that are partially
   1088  *     applied to the function.
   1089  * @return {!Function} A partially-applied form of the function bind() was
   1090  *     invoked as a method of.
   1091  * @suppress {deprecated} See above.
   1092  */
   1093 goog.bind = function(fn, selfObj, var_args) {
   1094   // TODO(nicksantos): narrow the type signature.
   1095   if (Function.prototype.bind &&
   1096       // NOTE(nicksantos): Somebody pulled base.js into the default
   1097       // Chrome extension environment. This means that for Chrome extensions,
   1098       // they get the implementation of Function.prototype.bind that
   1099       // calls goog.bind instead of the native one. Even worse, we don't want
   1100       // to introduce a circular dependency between goog.bind and
   1101       // Function.prototype.bind, so we have to hack this to make sure it
   1102       // works correctly.
   1103       Function.prototype.bind.toString().indexOf('native code') != -1) {
   1104     goog.bind = goog.bindNative_;
   1105   } else {
   1106     goog.bind = goog.bindJs_;
   1107   }
   1108   return goog.bind.apply(null, arguments);
   1109 };
   1110 
   1111 
   1112 /**
   1113  * Like bind(), except that a 'this object' is not required. Useful when the
   1114  * target function is already bound.
   1115  *
   1116  * Usage:
   1117  * var g = partial(f, arg1, arg2);
   1118  * g(arg3, arg4);
   1119  *
   1120  * @param {Function} fn A function to partially apply.
   1121  * @param {...*} var_args Additional arguments that are partially
   1122  *     applied to fn.
   1123  * @return {!Function} A partially-applied form of the function bind() was
   1124  *     invoked as a method of.
   1125  */
   1126 goog.partial = function(fn, var_args) {
   1127   var args = Array.prototype.slice.call(arguments, 1);
   1128   return function() {
   1129     // Prepend the bound arguments to the current arguments.
   1130     var newArgs = Array.prototype.slice.call(arguments);
   1131     newArgs.unshift.apply(newArgs, args);
   1132     return fn.apply(this, newArgs);
   1133   };
   1134 };
   1135 
   1136 
   1137 /**
   1138  * Copies all the members of a source object to a target object. This method
   1139  * does not work on all browsers for all objects that contain keys such as
   1140  * toString or hasOwnProperty. Use goog.object.extend for this purpose.
   1141  * @param {Object} target Target.
   1142  * @param {Object} source Source.
   1143  */
   1144 goog.mixin = function(target, source) {
   1145   for (var x in source) {
   1146     target[x] = source[x];
   1147   }
   1148 
   1149   // For IE7 or lower, the for-in-loop does not contain any properties that are
   1150   // not enumerable on the prototype object (for example, isPrototypeOf from
   1151   // Object.prototype) but also it will not include 'replace' on objects that
   1152   // extend String and change 'replace' (not that it is common for anyone to
   1153   // extend anything except Object).
   1154 };
   1155 
   1156 
   1157 /**
   1158  * @return {number} An integer value representing the number of milliseconds
   1159  *     between midnight, January 1, 1970 and the current time.
   1160  */
   1161 goog.now = Date.now || (function() {
   1162   // Unary plus operator converts its operand to a number which in the case of
   1163   // a date is done by calling getTime().
   1164   return +new Date();
   1165 });
   1166 
   1167 
   1168 /**
   1169  * Evals javascript in the global scope.  In IE this uses execScript, other
   1170  * browsers use goog.global.eval. If goog.global.eval does not evaluate in the
   1171  * global scope (for example, in Safari), appends a script tag instead.
   1172  * Throws an exception if neither execScript or eval is defined.
   1173  * @param {string} script JavaScript string.
   1174  */
   1175 goog.globalEval = function(script) {
   1176   if (goog.global.execScript) {
   1177     goog.global.execScript(script, 'JavaScript');
   1178   } else if (goog.global.eval) {
   1179     // Test to see if eval works
   1180     if (goog.evalWorksForGlobals_ == null) {
   1181       goog.global.eval('var _et_ = 1;');
   1182       if (typeof goog.global['_et_'] != 'undefined') {
   1183         delete goog.global['_et_'];
   1184         goog.evalWorksForGlobals_ = true;
   1185       } else {
   1186         goog.evalWorksForGlobals_ = false;
   1187       }
   1188     }
   1189 
   1190     if (goog.evalWorksForGlobals_) {
   1191       goog.global.eval(script);
   1192     } else {
   1193       var doc = goog.global.document;
   1194       var scriptElt = doc.createElement('script');
   1195       scriptElt.type = 'text/javascript';
   1196       scriptElt.defer = false;
   1197       // Note(user): can't use .innerHTML since "t('<test>')" will fail and
   1198       // .text doesn't work in Safari 2.  Therefore we append a text node.
   1199       scriptElt.appendChild(doc.createTextNode(script));
   1200       doc.body.appendChild(scriptElt);
   1201       doc.body.removeChild(scriptElt);
   1202     }
   1203   } else {
   1204     throw Error('goog.globalEval not available');
   1205   }
   1206 };
   1207 
   1208 
   1209 /**
   1210  * Indicates whether or not we can call 'eval' directly to eval code in the
   1211  * global scope. Set to a Boolean by the first call to goog.globalEval (which
   1212  * empirically tests whether eval works for globals). @see goog.globalEval
   1213  * @type {?boolean}
   1214  * @private
   1215  */
   1216 goog.evalWorksForGlobals_ = null;
   1217 
   1218 
   1219 /**
   1220  * Optional map of CSS class names to obfuscated names used with
   1221  * goog.getCssName().
   1222  * @type {Object|undefined}
   1223  * @private
   1224  * @see goog.setCssNameMapping
   1225  */
   1226 goog.cssNameMapping_;
   1227 
   1228 
   1229 /**
   1230  * Optional obfuscation style for CSS class names. Should be set to either
   1231  * 'BY_WHOLE' or 'BY_PART' if defined.
   1232  * @type {string|undefined}
   1233  * @private
   1234  * @see goog.setCssNameMapping
   1235  */
   1236 goog.cssNameMappingStyle_;
   1237 
   1238 
   1239 /**
   1240  * Handles strings that are intended to be used as CSS class names.
   1241  *
   1242  * This function works in tandem with @see goog.setCssNameMapping.
   1243  *
   1244  * Without any mapping set, the arguments are simple joined with a
   1245  * hyphen and passed through unaltered.
   1246  *
   1247  * When there is a mapping, there are two possible styles in which
   1248  * these mappings are used. In the BY_PART style, each part (i.e. in
   1249  * between hyphens) of the passed in css name is rewritten according
   1250  * to the map. In the BY_WHOLE style, the full css name is looked up in
   1251  * the map directly. If a rewrite is not specified by the map, the
   1252  * compiler will output a warning.
   1253  *
   1254  * When the mapping is passed to the compiler, it will replace calls
   1255  * to goog.getCssName with the strings from the mapping, e.g.
   1256  *     var x = goog.getCssName('foo');
   1257  *     var y = goog.getCssName(this.baseClass, 'active');
   1258  *  becomes:
   1259  *     var x= 'foo';
   1260  *     var y = this.baseClass + '-active';
   1261  *
   1262  * If one argument is passed it will be processed, if two are passed
   1263  * only the modifier will be processed, as it is assumed the first
   1264  * argument was generated as a result of calling goog.getCssName.
   1265  *
   1266  * @param {string} className The class name.
   1267  * @param {string=} opt_modifier A modifier to be appended to the class name.
   1268  * @return {string} The class name or the concatenation of the class name and
   1269  *     the modifier.
   1270  */
   1271 goog.getCssName = function(className, opt_modifier) {
   1272   var getMapping = function(cssName) {
   1273     return goog.cssNameMapping_[cssName] || cssName;
   1274   };
   1275 
   1276   var renameByParts = function(cssName) {
   1277     // Remap all the parts individually.
   1278     var parts = cssName.split('-');
   1279     var mapped = [];
   1280     for (var i = 0; i < parts.length; i++) {
   1281       mapped.push(getMapping(parts[i]));
   1282     }
   1283     return mapped.join('-');
   1284   };
   1285 
   1286   var rename;
   1287   if (goog.cssNameMapping_) {
   1288     rename = goog.cssNameMappingStyle_ == 'BY_WHOLE' ?
   1289         getMapping : renameByParts;
   1290   } else {
   1291     rename = function(a) {
   1292       return a;
   1293     };
   1294   }
   1295 
   1296   if (opt_modifier) {
   1297     return className + '-' + rename(opt_modifier);
   1298   } else {
   1299     return rename(className);
   1300   }
   1301 };
   1302 
   1303 
   1304 /**
   1305  * Sets the map to check when returning a value from goog.getCssName(). Example:
   1306  * <pre>
   1307  * goog.setCssNameMapping({
   1308  *   "goog": "a",
   1309  *   "disabled": "b",
   1310  * });
   1311  *
   1312  * var x = goog.getCssName('goog');
   1313  * // The following evaluates to: "a a-b".
   1314  * goog.getCssName('goog') + ' ' + goog.getCssName(x, 'disabled')
   1315  * </pre>
   1316  * When declared as a map of string literals to string literals, the JSCompiler
   1317  * will replace all calls to goog.getCssName() using the supplied map if the
   1318  * --closure_pass flag is set.
   1319  *
   1320  * @param {!Object} mapping A map of strings to strings where keys are possible
   1321  *     arguments to goog.getCssName() and values are the corresponding values
   1322  *     that should be returned.
   1323  * @param {string=} style The style of css name mapping. There are two valid
   1324  *     options: 'BY_PART', and 'BY_WHOLE'.
   1325  * @see goog.getCssName for a description.
   1326  */
   1327 goog.setCssNameMapping = function(mapping, style) {
   1328   goog.cssNameMapping_ = mapping;
   1329   goog.cssNameMappingStyle_ = style;
   1330 };
   1331 
   1332 
   1333 /**
   1334  * Abstract implementation of goog.getMsg for use with localized messages.
   1335  * @param {string} str Translatable string, places holders in the form {$foo}.
   1336  * @param {Object=} opt_values Map of place holder name to value.
   1337  * @return {string} message with placeholders filled.
   1338  */
   1339 goog.getMsg = function(str, opt_values) {
   1340   var values = opt_values || {};
   1341   for (var key in values) {
   1342     var value = ('' + values[key]).replace(/\$/g, '$$$$');
   1343     str = str.replace(new RegExp('\\{\\$' + key + '\\}', 'gi'), value);
   1344   }
   1345   return str;
   1346 };
   1347 
   1348 
   1349 /**
   1350  * Exposes an unobfuscated global namespace path for the given object.
   1351  * Note that fields of the exported object *will* be obfuscated,
   1352  * unless they are exported in turn via this function or
   1353  * goog.exportProperty
   1354  *
   1355  * <p>Also handy for making public items that are defined in anonymous
   1356  * closures.
   1357  *
   1358  * ex. goog.exportSymbol('Foo', Foo);
   1359  *
   1360  * ex. goog.exportSymbol('public.path.Foo.staticFunction',
   1361  *                       Foo.staticFunction);
   1362  *     public.path.Foo.staticFunction();
   1363  *
   1364  * ex. goog.exportSymbol('public.path.Foo.prototype.myMethod',
   1365  *                       Foo.prototype.myMethod);
   1366  *     new public.path.Foo().myMethod();
   1367  *
   1368  * @param {string} publicPath Unobfuscated name to export.
   1369  * @param {*} object Object the name should point to.
   1370  * @param {Object=} opt_objectToExportTo The object to add the path to; default
   1371  *     is |goog.global|.
   1372  */
   1373 goog.exportSymbol = function(publicPath, object, opt_objectToExportTo) {
   1374   goog.exportPath_(publicPath, object, opt_objectToExportTo);
   1375 };
   1376 
   1377 
   1378 /**
   1379  * Exports a property unobfuscated into the object's namespace.
   1380  * ex. goog.exportProperty(Foo, 'staticFunction', Foo.staticFunction);
   1381  * ex. goog.exportProperty(Foo.prototype, 'myMethod', Foo.prototype.myMethod);
   1382  * @param {Object} object Object whose static property is being exported.
   1383  * @param {string} publicName Unobfuscated name to export.
   1384  * @param {*} symbol Object the name should point to.
   1385  */
   1386 goog.exportProperty = function(object, publicName, symbol) {
   1387   object[publicName] = symbol;
   1388 };
   1389 
   1390 
   1391 /**
   1392  * Inherit the prototype methods from one constructor into another.
   1393  *
   1394  * Usage:
   1395  * <pre>
   1396  * function ParentClass(a, b) { }
   1397  * ParentClass.prototype.foo = function(a) { }
   1398  *
   1399  * function ChildClass(a, b, c) {
   1400  *   ParentClass.call(this, a, b);
   1401  * }
   1402  *
   1403  * goog.inherits(ChildClass, ParentClass);
   1404  *
   1405  * var child = new ChildClass('a', 'b', 'see');
   1406  * child.foo(); // works
   1407  * </pre>
   1408  *
   1409  * In addition, a superclass' implementation of a method can be invoked
   1410  * as follows:
   1411  *
   1412  * <pre>
   1413  * ChildClass.prototype.foo = function(a) {
   1414  *   ChildClass.superClass_.foo.call(this, a);
   1415  *   // other code
   1416  * };
   1417  * </pre>
   1418  *
   1419  * @param {Function} childCtor Child class.
   1420  * @param {Function} parentCtor Parent class.
   1421  */
   1422 goog.inherits = function(childCtor, parentCtor) {
   1423   /** @constructor */
   1424   function tempCtor() {};
   1425   tempCtor.prototype = parentCtor.prototype;
   1426   childCtor.superClass_ = parentCtor.prototype;
   1427   childCtor.prototype = new tempCtor();
   1428   childCtor.prototype.constructor = childCtor;
   1429 };
   1430 
   1431 
   1432 /**
   1433  * Call up to the superclass.
   1434  *
   1435  * If this is called from a constructor, then this calls the superclass
   1436  * contructor with arguments 1-N.
   1437  *
   1438  * If this is called from a prototype method, then you must pass
   1439  * the name of the method as the second argument to this function. If
   1440  * you do not, you will get a runtime error. This calls the superclass'
   1441  * method with arguments 2-N.
   1442  *
   1443  * This function only works if you use goog.inherits to express
   1444  * inheritance relationships between your classes.
   1445  *
   1446  * This function is a compiler primitive. At compile-time, the
   1447  * compiler will do macro expansion to remove a lot of
   1448  * the extra overhead that this function introduces. The compiler
   1449  * will also enforce a lot of the assumptions that this function
   1450  * makes, and treat it as a compiler error if you break them.
   1451  *
   1452  * @param {!Object} me Should always be "this".
   1453  * @param {*=} opt_methodName The method name if calling a super method.
   1454  * @param {...*} var_args The rest of the arguments.
   1455  * @return {*} The return value of the superclass method.
   1456  */
   1457 goog.base = function(me, opt_methodName, var_args) {
   1458   var caller = arguments.callee.caller;
   1459   if (caller.superClass_) {
   1460     // This is a constructor. Call the superclass constructor.
   1461     return caller.superClass_.constructor.apply(
   1462         me, Array.prototype.slice.call(arguments, 1));
   1463   }
   1464 
   1465   var args = Array.prototype.slice.call(arguments, 2);
   1466   var foundCaller = false;
   1467   for (var ctor = me.constructor;
   1468        ctor; ctor = ctor.superClass_ && ctor.superClass_.constructor) {
   1469     if (ctor.prototype[opt_methodName] === caller) {
   1470       foundCaller = true;
   1471     } else if (foundCaller) {
   1472       return ctor.prototype[opt_methodName].apply(me, args);
   1473     }
   1474   }
   1475 
   1476   // If we did not find the caller in the prototype chain,
   1477   // then one of two things happened:
   1478   // 1) The caller is an instance method.
   1479   // 2) This method was not called by the right caller.
   1480   if (me[opt_methodName] === caller) {
   1481     return me.constructor.prototype[opt_methodName].apply(me, args);
   1482   } else {
   1483     throw Error(
   1484         'goog.base called from a method of one name ' +
   1485         'to a method of a different name');
   1486   }
   1487 };
   1488 
   1489 
   1490 /**
   1491  * Allow for aliasing within scope functions.  This function exists for
   1492  * uncompiled code - in compiled code the calls will be inlined and the
   1493  * aliases applied.  In uncompiled code the function is simply run since the
   1494  * aliases as written are valid JavaScript.
   1495  * @param {function()} fn Function to call.  This function can contain aliases
   1496  *     to namespaces (e.g. "var dom = goog.dom") or classes
   1497  *    (e.g. "var Timer = goog.Timer").
   1498  */
   1499 goog.scope = function(fn) {
   1500   fn.call(goog.global);
   1501 };
   1502 
   1503 
   1504