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