lib/goog/base.js

1// Copyright 2006 The Closure Library Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License 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 * @author arv@google.com (Erik Arvidsson)
23 *
24 * @provideGoog
25 */
26
27
28/**
29 * @define {boolean} Overridden to true by the compiler when --closure_pass
30 * or --mark_as_compiled is specified.
31 */
32var COMPILED = false;
33
34
35/**
36 * Base namespace for the Closure library. Checks to see goog is already
37 * defined in the current scope before assigning to prevent clobbering if
38 * base.js is loaded more than once.
39 *
40 * @const
41 */
42var goog = goog || {};
43
44
45/**
46 * Reference to the global context. In most cases this will be 'window'.
47 */
48goog.global = this;
49
50
51/**
52 * A hook for overriding the define values in uncompiled mode.
53 *
54 * In uncompiled mode, {@code CLOSURE_UNCOMPILED_DEFINES} may be defined before
55 * loading base.js. If a key is defined in {@code CLOSURE_UNCOMPILED_DEFINES},
56 * {@code goog.define} will use the value instead of the default value. This
57 * allows flags to be overwritten without compilation (this is normally
58 * accomplished with the compiler's "define" flag).
59 *
60 * Example:
61 * <pre>
62 * var CLOSURE_UNCOMPILED_DEFINES = {'goog.DEBUG': false};
63 * </pre>
64 *
65 * @type {Object<string, (string|number|boolean)>|undefined}
66 */
67goog.global.CLOSURE_UNCOMPILED_DEFINES;
68
69
70/**
71 * A hook for overriding the define values in uncompiled or compiled mode,
72 * like CLOSURE_UNCOMPILED_DEFINES but effective in compiled code. In
73 * uncompiled code CLOSURE_UNCOMPILED_DEFINES takes precedence.
74 *
75 * Also unlike CLOSURE_UNCOMPILED_DEFINES the values must be number, boolean or
76 * string literals or the compiler will emit an error.
77 *
78 * While any @define value may be set, only those set with goog.define will be
79 * effective for uncompiled code.
80 *
81 * Example:
82 * <pre>
83 * var CLOSURE_DEFINES = {'goog.DEBUG': false} ;
84 * </pre>
85 *
86 * @type {Object<string, (string|number|boolean)>|undefined}
87 */
88goog.global.CLOSURE_DEFINES;
89
90
91/**
92 * Returns true if the specified value is not undefined.
93 * WARNING: Do not use this to test if an object has a property. Use the in
94 * operator instead.
95 *
96 * @param {?} val Variable to test.
97 * @return {boolean} Whether variable is defined.
98 */
99goog.isDef = function(val) {
100 // void 0 always evaluates to undefined and hence we do not need to depend on
101 // the definition of the global variable named 'undefined'.
102 return val !== void 0;
103};
104
105
106/**
107 * Builds an object structure for the provided namespace path, ensuring that
108 * names that already exist are not overwritten. For example:
109 * "a.b.c" -> a = {};a.b={};a.b.c={};
110 * Used by goog.provide and goog.exportSymbol.
111 * @param {string} name name of the object that this file defines.
112 * @param {*=} opt_object the object to expose at the end of the path.
113 * @param {Object=} opt_objectToExportTo The object to add the path to; default
114 * is |goog.global|.
115 * @private
116 */
117goog.exportPath_ = function(name, opt_object, opt_objectToExportTo) {
118 var parts = name.split('.');
119 var cur = opt_objectToExportTo || goog.global;
120
121 // Internet Explorer exhibits strange behavior when throwing errors from
122 // methods externed in this manner. See the testExportSymbolExceptions in
123 // base_test.html for an example.
124 if (!(parts[0] in cur) && cur.execScript) {
125 cur.execScript('var ' + parts[0]);
126 }
127
128 // Certain browsers cannot parse code in the form for((a in b); c;);
129 // This pattern is produced by the JSCompiler when it collapses the
130 // statement above into the conditional loop below. To prevent this from
131 // happening, use a for-loop and reserve the init logic as below.
132
133 // Parentheses added to eliminate strict JS warning in Firefox.
134 for (var part; parts.length && (part = parts.shift());) {
135 if (!parts.length && goog.isDef(opt_object)) {
136 // last part and we have an object; use it
137 cur[part] = opt_object;
138 } else if (cur[part]) {
139 cur = cur[part];
140 } else {
141 cur = cur[part] = {};
142 }
143 }
144};
145
146
147/**
148 * Defines a named value. In uncompiled mode, the value is retreived from
149 * CLOSURE_DEFINES or CLOSURE_UNCOMPILED_DEFINES if the object is defined and
150 * has the property specified, and otherwise used the defined defaultValue.
151 * When compiled the default can be overridden using the compiler
152 * options or the value set in the CLOSURE_DEFINES object.
153 *
154 * @param {string} name The distinguished name to provide.
155 * @param {string|number|boolean} defaultValue
156 */
157goog.define = function(name, defaultValue) {
158 var value = defaultValue;
159 if (!COMPILED) {
160 if (goog.global.CLOSURE_UNCOMPILED_DEFINES &&
161 Object.prototype.hasOwnProperty.call(
162 goog.global.CLOSURE_UNCOMPILED_DEFINES, name)) {
163 value = goog.global.CLOSURE_UNCOMPILED_DEFINES[name];
164 } else if (goog.global.CLOSURE_DEFINES &&
165 Object.prototype.hasOwnProperty.call(
166 goog.global.CLOSURE_DEFINES, name)) {
167 value = goog.global.CLOSURE_DEFINES[name];
168 }
169 }
170 goog.exportPath_(name, value);
171};
172
173
174/**
175 * @define {boolean} DEBUG is provided as a convenience so that debugging code
176 * that should not be included in a production js_binary can be easily stripped
177 * by specifying --define goog.DEBUG=false to the JSCompiler. For example, most
178 * toString() methods should be declared inside an "if (goog.DEBUG)" conditional
179 * because they are generally used for debugging purposes and it is difficult
180 * for the JSCompiler to statically determine whether they are used.
181 */
182goog.DEBUG = true;
183
184
185/**
186 * @define {string} LOCALE defines the locale being used for compilation. It is
187 * used to select locale specific data to be compiled in js binary. BUILD rule
188 * can specify this value by "--define goog.LOCALE=<locale_name>" as JSCompiler
189 * option.
190 *
191 * Take into account that the locale code format is important. You should use
192 * the canonical Unicode format with hyphen as a delimiter. Language must be
193 * lowercase, Language Script - Capitalized, Region - UPPERCASE.
194 * There are few examples: pt-BR, en, en-US, sr-Latin-BO, zh-Hans-CN.
195 *
196 * See more info about locale codes here:
197 * http://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers
198 *
199 * For language codes you should use values defined by ISO 693-1. See it here
200 * http://www.w3.org/WAI/ER/IG/ert/iso639.htm. There is only one exception from
201 * this rule: the Hebrew language. For legacy reasons the old code (iw) should
202 * be used instead of the new code (he), see http://wiki/Main/IIISynonyms.
203 */
204goog.define('goog.LOCALE', 'en'); // default to en
205
206
207/**
208 * @define {boolean} Whether this code is running on trusted sites.
209 *
210 * On untrusted sites, several native functions can be defined or overridden by
211 * external libraries like Prototype, Datejs, and JQuery and setting this flag
212 * to false forces closure to use its own implementations when possible.
213 *
214 * If your JavaScript can be loaded by a third party site and you are wary about
215 * relying on non-standard implementations, specify
216 * "--define goog.TRUSTED_SITE=false" to the JSCompiler.
217 */
218goog.define('goog.TRUSTED_SITE', true);
219
220
221/**
222 * @define {boolean} Whether a project is expected to be running in strict mode.
223 *
224 * This define can be used to trigger alternate implementations compatible with
225 * running in EcmaScript Strict mode or warn about unavailable functionality.
226 * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode
227 */
228goog.define('goog.STRICT_MODE_COMPATIBLE', false);
229
230
231/**
232 * Creates object stubs for a namespace. The presence of one or more
233 * goog.provide() calls indicate that the file defines the given
234 * objects/namespaces. Provided objects must not be null or undefined.
235 * Build tools also scan for provide/require statements
236 * to discern dependencies, build dependency files (see deps.js), etc.
237 * @see goog.require
238 * @param {string} name Namespace provided by this file in the form
239 * "goog.package.part".
240 */
241goog.provide = function(name) {
242 if (!COMPILED) {
243 // Ensure that the same namespace isn't provided twice.
244 // A goog.module/goog.provide maps a goog.require to a specific file
245 if (goog.isProvided_(name)) {
246 throw Error('Namespace "' + name + '" already declared.');
247 }
248 }
249
250 goog.constructNamespace_(name);
251};
252
253
254/**
255 * @param {string} name Namespace provided by this file in the form
256 * "goog.package.part".
257 * @param {Object=} opt_obj The object to embed in the namespace.
258 * @private
259 */
260goog.constructNamespace_ = function(name, opt_obj) {
261 if (!COMPILED) {
262 delete goog.implicitNamespaces_[name];
263
264 var namespace = name;
265 while ((namespace = namespace.substring(0, namespace.lastIndexOf('.')))) {
266 if (goog.getObjectByName(namespace)) {
267 break;
268 }
269 goog.implicitNamespaces_[namespace] = true;
270 }
271 }
272
273 goog.exportPath_(name, opt_obj);
274};
275
276
277/**
278 * Module identifier validation regexp.
279 * Note: This is a conservative check, it is very possible to be more lienent,
280 * the primary exclusion here is "/" and "\" and a leading ".", these
281 * restrictions are intended to leave the door open for using goog.require
282 * with relative file paths rather than module identifiers.
283 * @private
284 */
285goog.VALID_MODULE_RE_ = /^[a-zA-Z_$][a-zA-Z0-9._$]*$/;
286
287
288/**
289 * goog.module serves two purposes:
290 * - marks a file that must be loaded as a module
291 * - reserves a namespace (it can not also be goog.provided)
292 * and has three requirements:
293 * - goog.module may not be used in the same file as goog.provide.
294 * - goog.module must be the first statement in the file.
295 * - only one goog.module is allowed per file.
296 * When a goog.module annotated file is loaded, it is loaded enclosed in
297 * a strict function closure. This means that:
298 * - any variable declared in a goog.module file are private to the file,
299 * not global. Although the compiler is expected to inline the module.
300 * - The code must obey all the rules of "strict" JavaScript.
301 * - the file will be marked as "use strict"
302 *
303 * NOTE: unlike goog.provide, goog.module does not declare any symbols by
304 * itself.
305 *
306 * @param {string} name Namespace provided by this file in the form
307 * "goog.package.part", is expected but not required.
308 */
309goog.module = function(name) {
310 if (!goog.isString(name) ||
311 !name ||
312 name.search(goog.VALID_MODULE_RE_) == -1) {
313 throw Error('Invalid module identifier');
314 }
315 if (!goog.isInModuleLoader_()) {
316 throw Error('Module ' + name + ' has been loaded incorrectly.');
317 }
318 if (goog.moduleLoaderState_.moduleName) {
319 throw Error('goog.module may only be called once per module.');
320 }
321
322 // Store the module name for the loader.
323 goog.moduleLoaderState_.moduleName = name;
324 if (!COMPILED) {
325 // Ensure that the same namespace isn't provided twice.
326 // A goog.module/goog.provide maps a goog.require to a specific file
327 if (goog.isProvided_(name)) {
328 throw Error('Namespace "' + name + '" already declared.');
329 }
330 delete goog.implicitNamespaces_[name];
331 }
332};
333
334
335/**
336 * @param {string} name The module identifier.
337 * @return {?} The module exports for an already loaded module or null.
338 *
339 * Note: This is not an alternative to goog.require, it does not
340 * indicate a hard dependency, instead it is used to indicate
341 * an optional dependency or to access the exports of a module
342 * that has already been loaded.
343 */
344goog.module.get = function(name) {
345 return goog.module.getInternal_(name);
346};
347
348
349/**
350 * @param {string} name The module identifier.
351 * @return {?} The module exports for an already loaded module or null.
352 * @private
353 */
354goog.module.getInternal_ = function(name) {
355 if (!COMPILED) {
356 if (goog.isProvided_(name)) {
357 // goog.require only return a value with-in goog.module files.
358 return name in goog.loadedModules_ ?
359 goog.loadedModules_[name] :
360 goog.getObjectByName(name);
361 } else {
362 return null;
363 }
364 }
365};
366
367
368/**
369 * @private {?{
370 * moduleName: (string|undefined),
371 * declareTestMethods: boolean
372 * }}
373 */
374goog.moduleLoaderState_ = null;
375
376
377/**
378 * @private
379 * @return {boolean} Whether a goog.module is currently being initialized.
380 */
381goog.isInModuleLoader_ = function() {
382 return goog.moduleLoaderState_ != null;
383};
384
385
386/**
387 * Indicate that a module's exports that are known test methods should
388 * be copied to the global object. This makes the test methods visible to
389 * test runners that inspect the global object.
390 *
391 * TODO(johnlenz): Make the test framework aware of goog.module so
392 * that this isn't necessary. Alternately combine this with goog.setTestOnly
393 * to minimize boiler plate.
394 */
395goog.module.declareTestMethods = function() {
396 if (!goog.isInModuleLoader_()) {
397 throw new Error('goog.module.declareTestMethods must be called from ' +
398 'within a goog.module');
399 }
400 goog.moduleLoaderState_.declareTestMethods = true;
401};
402
403
404/**
405 * Provide the module's exports as a globally accessible object under the
406 * module's declared name. This is intended to ease migration to goog.module
407 * for files that have existing usages.
408 */
409goog.module.declareLegacyNamespace = function() {
410 if (!COMPILED && !goog.isInModuleLoader_()) {
411 throw new Error('goog.module.declareLegacyNamespace must be called from ' +
412 'within a goog.module');
413 }
414 if (!COMPILED && !goog.moduleLoaderState_.moduleName) {
415 throw Error('goog.module must be called prior to ' +
416 'goog.module.declareLegacyNamespace.');
417 }
418 goog.moduleLoaderState_.declareLegacyNamespace = true;
419};
420
421
422/**
423 * Marks that the current file should only be used for testing, and never for
424 * live code in production.
425 *
426 * In the case of unit tests, the message may optionally be an exact namespace
427 * for the test (e.g. 'goog.stringTest'). The linter will then ignore the extra
428 * provide (if not explicitly defined in the code).
429 *
430 * @param {string=} opt_message Optional message to add to the error that's
431 * raised when used in production code.
432 */
433goog.setTestOnly = function(opt_message) {
434 if (COMPILED && !goog.DEBUG) {
435 opt_message = opt_message || '';
436 throw Error('Importing test-only code into non-debug environment' +
437 (opt_message ? ': ' + opt_message : '.'));
438 }
439};
440
441
442/**
443 * Forward declares a symbol. This is an indication to the compiler that the
444 * symbol may be used in the source yet is not required and may not be provided
445 * in compilation.
446 *
447 * The most common usage of forward declaration is code that takes a type as a
448 * function parameter but does not need to require it. By forward declaring
449 * instead of requiring, no hard dependency is made, and (if not required
450 * elsewhere) the namespace may never be required and thus, not be pulled
451 * into the JavaScript binary. If it is required elsewhere, it will be type
452 * checked as normal.
453 *
454 *
455 * @param {string} name The namespace to forward declare in the form of
456 * "goog.package.part".
457 */
458goog.forwardDeclare = function(name) {};
459
460
461if (!COMPILED) {
462
463 /**
464 * Check if the given name has been goog.provided. This will return false for
465 * names that are available only as implicit namespaces.
466 * @param {string} name name of the object to look for.
467 * @return {boolean} Whether the name has been provided.
468 * @private
469 */
470 goog.isProvided_ = function(name) {
471 return (name in goog.loadedModules_) ||
472 (!goog.implicitNamespaces_[name] &&
473 goog.isDefAndNotNull(goog.getObjectByName(name)));
474 };
475
476 /**
477 * Namespaces implicitly defined by goog.provide. For example,
478 * goog.provide('goog.events.Event') implicitly declares that 'goog' and
479 * 'goog.events' must be namespaces.
480 *
481 * @type {!Object<string, (boolean|undefined)>}
482 * @private
483 */
484 goog.implicitNamespaces_ = {'goog.module': true};
485
486 // NOTE: We add goog.module as an implicit namespace as goog.module is defined
487 // here and because the existing module package has not been moved yet out of
488 // the goog.module namespace. This satisifies both the debug loader and
489 // ahead-of-time dependency management.
490}
491
492
493/**
494 * Returns an object based on its fully qualified external name. The object
495 * is not found if null or undefined. If you are using a compilation pass that
496 * renames property names beware that using this function will not find renamed
497 * properties.
498 *
499 * @param {string} name The fully qualified name.
500 * @param {Object=} opt_obj The object within which to look; default is
501 * |goog.global|.
502 * @return {?} The value (object or primitive) or, if not found, null.
503 */
504goog.getObjectByName = function(name, opt_obj) {
505 var parts = name.split('.');
506 var cur = opt_obj || goog.global;
507 for (var part; part = parts.shift(); ) {
508 if (goog.isDefAndNotNull(cur[part])) {
509 cur = cur[part];
510 } else {
511 return null;
512 }
513 }
514 return cur;
515};
516
517
518/**
519 * Globalizes a whole namespace, such as goog or goog.lang.
520 *
521 * @param {!Object} obj The namespace to globalize.
522 * @param {Object=} opt_global The object to add the properties to.
523 * @deprecated Properties may be explicitly exported to the global scope, but
524 * this should no longer be done in bulk.
525 */
526goog.globalize = function(obj, opt_global) {
527 var global = opt_global || goog.global;
528 for (var x in obj) {
529 global[x] = obj[x];
530 }
531};
532
533
534/**
535 * Adds a dependency from a file to the files it requires.
536 * @param {string} relPath The path to the js file.
537 * @param {!Array<string>} provides An array of strings with
538 * the names of the objects this file provides.
539 * @param {!Array<string>} requires An array of strings with
540 * the names of the objects this file requires.
541 * @param {boolean=} opt_isModule Whether this dependency must be loaded as
542 * a module as declared by goog.module.
543 */
544goog.addDependency = function(relPath, provides, requires, opt_isModule) {
545 if (goog.DEPENDENCIES_ENABLED) {
546 var provide, require;
547 var path = relPath.replace(/\\/g, '/');
548 var deps = goog.dependencies_;
549 for (var i = 0; provide = provides[i]; i++) {
550 deps.nameToPath[provide] = path;
551 deps.pathIsModule[path] = !!opt_isModule;
552 }
553 for (var j = 0; require = requires[j]; j++) {
554 if (!(path in deps.requires)) {
555 deps.requires[path] = {};
556 }
557 deps.requires[path][require] = true;
558 }
559 }
560};
561
562
563
564
565// NOTE(nnaze): The debug DOM loader was included in base.js as an original way
566// to do "debug-mode" development. The dependency system can sometimes be
567// confusing, as can the debug DOM loader's asynchronous nature.
568//
569// With the DOM loader, a call to goog.require() is not blocking -- the script
570// will not load until some point after the current script. If a namespace is
571// needed at runtime, it needs to be defined in a previous script, or loaded via
572// require() with its registered dependencies.
573// User-defined namespaces may need their own deps file. See http://go/js_deps,
574// http://go/genjsdeps, or, externally, DepsWriter.
575// https://developers.google.com/closure/library/docs/depswriter
576//
577// Because of legacy clients, the DOM loader can't be easily removed from
578// base.js. Work is being done to make it disableable or replaceable for
579// different environments (DOM-less JavaScript interpreters like Rhino or V8,
580// for example). See bootstrap/ for more information.
581
582
583/**
584 * @define {boolean} Whether to enable the debug loader.
585 *
586 * If enabled, a call to goog.require() will attempt to load the namespace by
587 * appending a script tag to the DOM (if the namespace has been registered).
588 *
589 * If disabled, goog.require() will simply assert that the namespace has been
590 * provided (and depend on the fact that some outside tool correctly ordered
591 * the script).
592 */
593goog.define('goog.ENABLE_DEBUG_LOADER', true);
594
595
596/**
597 * @param {string} msg
598 * @private
599 */
600goog.logToConsole_ = function(msg) {
601 if (goog.global.console) {
602 goog.global.console['error'](msg);
603 }
604};
605
606
607/**
608 * Implements a system for the dynamic resolution of dependencies that works in
609 * parallel with the BUILD system. Note that all calls to goog.require will be
610 * stripped by the JSCompiler when the --closure_pass option is used.
611 * @see goog.provide
612 * @param {string} name Namespace to include (as was given in goog.provide()) in
613 * the form "goog.package.part".
614 * @return {?} If called within a goog.module file, the associated namespace or
615 * module otherwise null.
616 */
617goog.require = function(name) {
618
619 // If the object already exists we do not need do do anything.
620 if (!COMPILED) {
621 if (goog.ENABLE_DEBUG_LOADER && goog.IS_OLD_IE_) {
622 goog.maybeProcessDeferredDep_(name);
623 }
624
625 if (goog.isProvided_(name)) {
626 if (goog.isInModuleLoader_()) {
627 return goog.module.getInternal_(name);
628 } else {
629 return null;
630 }
631 }
632
633 if (goog.ENABLE_DEBUG_LOADER) {
634 var path = goog.getPathFromDeps_(name);
635 if (path) {
636 goog.included_[path] = true;
637 goog.writeScripts_();
638 return null;
639 }
640 }
641
642 var errorMessage = 'goog.require could not find: ' + name;
643 goog.logToConsole_(errorMessage);
644
645 throw Error(errorMessage);
646 }
647};
648
649
650/**
651 * Path for included scripts.
652 * @type {string}
653 */
654goog.basePath = '';
655
656
657/**
658 * A hook for overriding the base path.
659 * @type {string|undefined}
660 */
661goog.global.CLOSURE_BASE_PATH;
662
663
664/**
665 * Whether to write out Closure's deps file. By default, the deps are written.
666 * @type {boolean|undefined}
667 */
668goog.global.CLOSURE_NO_DEPS;
669
670
671/**
672 * A function to import a single script. This is meant to be overridden when
673 * Closure is being run in non-HTML contexts, such as web workers. It's defined
674 * in the global scope so that it can be set before base.js is loaded, which
675 * allows deps.js to be imported properly.
676 *
677 * The function is passed the script source, which is a relative URI. It should
678 * return true if the script was imported, false otherwise.
679 * @type {(function(string): boolean)|undefined}
680 */
681goog.global.CLOSURE_IMPORT_SCRIPT;
682
683
684/**
685 * Null function used for default values of callbacks, etc.
686 * @return {void} Nothing.
687 */
688goog.nullFunction = function() {};
689
690
691/**
692 * The identity function. Returns its first argument.
693 *
694 * @param {*=} opt_returnValue The single value that will be returned.
695 * @param {...*} var_args Optional trailing arguments. These are ignored.
696 * @return {?} The first argument. We can't know the type -- just pass it along
697 * without type.
698 * @deprecated Use goog.functions.identity instead.
699 */
700goog.identityFunction = function(opt_returnValue, var_args) {
701 return opt_returnValue;
702};
703
704
705/**
706 * When defining a class Foo with an abstract method bar(), you can do:
707 * Foo.prototype.bar = goog.abstractMethod
708 *
709 * Now if a subclass of Foo fails to override bar(), an error will be thrown
710 * when bar() is invoked.
711 *
712 * Note: This does not take the name of the function to override as an argument
713 * because that would make it more difficult to obfuscate our JavaScript code.
714 *
715 * @type {!Function}
716 * @throws {Error} when invoked to indicate the method should be overridden.
717 */
718goog.abstractMethod = function() {
719 throw Error('unimplemented abstract method');
720};
721
722
723/**
724 * Adds a {@code getInstance} static method that always returns the same
725 * instance object.
726 * @param {!Function} ctor The constructor for the class to add the static
727 * method to.
728 */
729goog.addSingletonGetter = function(ctor) {
730 ctor.getInstance = function() {
731 if (ctor.instance_) {
732 return ctor.instance_;
733 }
734 if (goog.DEBUG) {
735 // NOTE: JSCompiler can't optimize away Array#push.
736 goog.instantiatedSingletons_[goog.instantiatedSingletons_.length] = ctor;
737 }
738 return ctor.instance_ = new ctor;
739 };
740};
741
742
743/**
744 * All singleton classes that have been instantiated, for testing. Don't read
745 * it directly, use the {@code goog.testing.singleton} module. The compiler
746 * removes this variable if unused.
747 * @type {!Array<!Function>}
748 * @private
749 */
750goog.instantiatedSingletons_ = [];
751
752
753/**
754 * @define {boolean} Whether to load goog.modules using {@code eval} when using
755 * the debug loader. This provides a better debugging experience as the
756 * source is unmodified and can be edited using Chrome Workspaces or
757 * similiar. However in some environments the use of {@code eval} is banned
758 * so we provide an alternative.
759 */
760goog.define('goog.LOAD_MODULE_USING_EVAL', true);
761
762
763/**
764 * @define {boolean} Whether the exports of goog.modules should be sealed when
765 * possible.
766 */
767goog.define('goog.SEAL_MODULE_EXPORTS', goog.DEBUG);
768
769
770/**
771 * The registry of initialized modules:
772 * the module identifier to module exports map.
773 * @private @const {!Object<string, ?>}
774 */
775goog.loadedModules_ = {};
776
777
778/**
779 * True if goog.dependencies_ is available.
780 * @const {boolean}
781 */
782goog.DEPENDENCIES_ENABLED = !COMPILED && goog.ENABLE_DEBUG_LOADER;
783
784
785if (goog.DEPENDENCIES_ENABLED) {
786 /**
787 * Object used to keep track of urls that have already been added. This record
788 * allows the prevention of circular dependencies.
789 * @private {!Object<string, boolean>}
790 */
791 goog.included_ = {};
792
793
794 /**
795 * This object is used to keep track of dependencies and other data that is
796 * used for loading scripts.
797 * @private
798 * @type {{
799 * pathIsModule: !Object<string, boolean>,
800 * nameToPath: !Object<string, string>,
801 * requires: !Object<string, !Object<string, boolean>>,
802 * visited: !Object<string, boolean>,
803 * written: !Object<string, boolean>,
804 * deferred: !Object<string, string>
805 * }}
806 */
807 goog.dependencies_ = {
808 pathIsModule: {}, // 1 to 1
809
810 nameToPath: {}, // 1 to 1
811
812 requires: {}, // 1 to many
813
814 // Used when resolving dependencies to prevent us from visiting file twice.
815 visited: {},
816
817 written: {}, // Used to keep track of script files we have written.
818
819 deferred: {} // Used to track deferred module evaluations in old IEs
820 };
821
822
823 /**
824 * Tries to detect whether is in the context of an HTML document.
825 * @return {boolean} True if it looks like HTML document.
826 * @private
827 */
828 goog.inHtmlDocument_ = function() {
829 var doc = goog.global.document;
830 return typeof doc != 'undefined' &&
831 'write' in doc; // XULDocument misses write.
832 };
833
834
835 /**
836 * Tries to detect the base path of base.js script that bootstraps Closure.
837 * @private
838 */
839 goog.findBasePath_ = function() {
840 if (goog.global.CLOSURE_BASE_PATH) {
841 goog.basePath = goog.global.CLOSURE_BASE_PATH;
842 return;
843 } else if (!goog.inHtmlDocument_()) {
844 return;
845 }
846 var doc = goog.global.document;
847 var scripts = doc.getElementsByTagName('script');
848 // Search backwards since the current script is in almost all cases the one
849 // that has base.js.
850 for (var i = scripts.length - 1; i >= 0; --i) {
851 var script = /** @type {!HTMLScriptElement} */ (scripts[i]);
852 var src = script.src;
853 var qmark = src.lastIndexOf('?');
854 var l = qmark == -1 ? src.length : qmark;
855 if (src.substr(l - 7, 7) == 'base.js') {
856 goog.basePath = src.substr(0, l - 7);
857 return;
858 }
859 }
860 };
861
862
863 /**
864 * Imports a script if, and only if, that script hasn't already been imported.
865 * (Must be called at execution time)
866 * @param {string} src Script source.
867 * @param {string=} opt_sourceText The optionally source text to evaluate
868 * @private
869 */
870 goog.importScript_ = function(src, opt_sourceText) {
871 var importScript = goog.global.CLOSURE_IMPORT_SCRIPT ||
872 goog.writeScriptTag_;
873 if (importScript(src, opt_sourceText)) {
874 goog.dependencies_.written[src] = true;
875 }
876 };
877
878
879 /** @const @private {boolean} */
880 goog.IS_OLD_IE_ = goog.global.document &&
881 goog.global.document.all && !goog.global.atob;
882
883
884 /**
885 * Given a URL initiate retrieval and execution of the module.
886 * @param {string} src Script source URL.
887 * @private
888 */
889 goog.importModule_ = function(src) {
890 // In an attempt to keep browsers from timing out loading scripts using
891 // synchronous XHRs, put each load in its own script block.
892 var bootstrap = 'goog.retrieveAndExecModule_("' + src + '");';
893
894 if (goog.importScript_('', bootstrap)) {
895 goog.dependencies_.written[src] = true;
896 }
897 };
898
899
900 /** @private {!Array<string>} */
901 goog.queuedModules_ = [];
902
903
904 /**
905 * Return an appropriate module text. Suitable to insert into
906 * a script tag (that is unescaped).
907 * @param {string} srcUrl
908 * @param {string} scriptText
909 * @return {string}
910 * @private
911 */
912 goog.wrapModule_ = function(srcUrl, scriptText) {
913 if (!goog.LOAD_MODULE_USING_EVAL || !goog.isDef(goog.global.JSON)) {
914 return '' +
915 'goog.loadModule(function(exports) {' +
916 '"use strict";' +
917 scriptText +
918 '\n' + // terminate any trailing single line comment.
919 ';return exports' +
920 '});' +
921 '\n//# sourceURL=' + srcUrl + '\n';
922 } else {
923 return '' +
924 'goog.loadModule(' +
925 goog.global.JSON.stringify(
926 scriptText + '\n//# sourceURL=' + srcUrl + '\n') +
927 ');';
928 }
929 };
930
931 // On IE9 and ealier, it is necessary to handle
932 // deferred module loads. In later browsers, the
933 // code to be evaluated is simply inserted as a script
934 // block in the correct order. To eval deferred
935 // code at the right time, we piggy back on goog.require to call
936 // goog.maybeProcessDeferredDep_.
937 //
938 // The goog.requires are used both to bootstrap
939 // the loading process (when no deps are available) and
940 // declare that they should be available.
941 //
942 // Here we eval the sources, if all the deps are available
943 // either already eval'd or goog.require'd. This will
944 // be the case when all the dependencies have already
945 // been loaded, and the dependent module is loaded.
946 //
947 // But this alone isn't sufficient because it is also
948 // necessary to handle the case where there is no root
949 // that is not deferred. For that there we register for an event
950 // and trigger goog.loadQueuedModules_ handle any remaining deferred
951 // evaluations.
952
953 /**
954 * Handle any remaining deferred goog.module evals.
955 * @private
956 */
957 goog.loadQueuedModules_ = function() {
958 var count = goog.queuedModules_.length;
959 if (count > 0) {
960 var queue = goog.queuedModules_;
961 goog.queuedModules_ = [];
962 for (var i = 0; i < count; i++) {
963 var path = queue[i];
964 goog.maybeProcessDeferredPath_(path);
965 }
966 }
967 };
968
969
970 /**
971 * Eval the named module if its dependencies are
972 * available.
973 * @param {string} name The module to load.
974 * @private
975 */
976 goog.maybeProcessDeferredDep_ = function(name) {
977 if (goog.isDeferredModule_(name) &&
978 goog.allDepsAreAvailable_(name)) {
979 var path = goog.getPathFromDeps_(name);
980 goog.maybeProcessDeferredPath_(goog.basePath + path);
981 }
982 };
983
984 /**
985 * @param {string} name The module to check.
986 * @return {boolean} Whether the name represents a
987 * module whose evaluation has been deferred.
988 * @private
989 */
990 goog.isDeferredModule_ = function(name) {
991 var path = goog.getPathFromDeps_(name);
992 if (path && goog.dependencies_.pathIsModule[path]) {
993 var abspath = goog.basePath + path;
994 return (abspath) in goog.dependencies_.deferred;
995 }
996 return false;
997 };
998
999 /**
1000 * @param {string} name The module to check.
1001 * @return {boolean} Whether the name represents a
1002 * module whose declared dependencies have all been loaded
1003 * (eval'd or a deferred module load)
1004 * @private
1005 */
1006 goog.allDepsAreAvailable_ = function(name) {
1007 var path = goog.getPathFromDeps_(name);
1008 if (path && (path in goog.dependencies_.requires)) {
1009 for (var requireName in goog.dependencies_.requires[path]) {
1010 if (!goog.isProvided_(requireName) &&
1011 !goog.isDeferredModule_(requireName)) {
1012 return false;
1013 }
1014 }
1015 }
1016 return true;
1017 };
1018
1019
1020 /**
1021 * @param {string} abspath
1022 * @private
1023 */
1024 goog.maybeProcessDeferredPath_ = function(abspath) {
1025 if (abspath in goog.dependencies_.deferred) {
1026 var src = goog.dependencies_.deferred[abspath];
1027 delete goog.dependencies_.deferred[abspath];
1028 goog.globalEval(src);
1029 }
1030 };
1031
1032
1033 /**
1034 * @param {function(?):?|string} moduleDef The module definition.
1035 */
1036 goog.loadModule = function(moduleDef) {
1037 // NOTE: we allow function definitions to be either in the from
1038 // of a string to eval (which keeps the original source intact) or
1039 // in a eval forbidden environment (CSP) we allow a function definition
1040 // which in its body must call {@code goog.module}, and return the exports
1041 // of the module.
1042 var previousState = goog.moduleLoaderState_;
1043 try {
1044 goog.moduleLoaderState_ = {
1045 moduleName: undefined, declareTestMethods: false};
1046 var exports;
1047 if (goog.isFunction(moduleDef)) {
1048 exports = moduleDef.call(goog.global, {});
1049 } else if (goog.isString(moduleDef)) {
1050 exports = goog.loadModuleFromSource_.call(goog.global, moduleDef);
1051 } else {
1052 throw Error('Invalid module definition');
1053 }
1054
1055 var moduleName = goog.moduleLoaderState_.moduleName;
1056 if (!goog.isString(moduleName) || !moduleName) {
1057 throw Error('Invalid module name \"' + moduleName + '\"');
1058 }
1059
1060 // Don't seal legacy namespaces as they may be uses as a parent of
1061 // another namespace
1062 if (goog.moduleLoaderState_.declareLegacyNamespace) {
1063 goog.constructNamespace_(moduleName, exports);
1064 } else if (goog.SEAL_MODULE_EXPORTS && Object.seal) {
1065 Object.seal(exports);
1066 }
1067
1068 goog.loadedModules_[moduleName] = exports;
1069 if (goog.moduleLoaderState_.declareTestMethods) {
1070 for (var entry in exports) {
1071 if (entry.indexOf('test', 0) === 0 ||
1072 entry == 'tearDown' ||
1073 entry == 'setUp' ||
1074 entry == 'setUpPage' ||
1075 entry == 'tearDownPage') {
1076 goog.global[entry] = exports[entry];
1077 }
1078 }
1079 }
1080 } finally {
1081 goog.moduleLoaderState_ = previousState;
1082 }
1083 };
1084
1085
1086 /**
1087 * @private @const {function(string):?}
1088 */
1089 goog.loadModuleFromSource_ = function() {
1090 // NOTE: we avoid declaring parameters or local variables here to avoid
1091 // masking globals or leaking values into the module definition.
1092 'use strict';
1093 var exports = {};
1094 eval(arguments[0]);
1095 return exports;
1096 };
1097
1098
1099 /**
1100 * The default implementation of the import function. Writes a script tag to
1101 * import the script.
1102 *
1103 * @param {string} src The script url.
1104 * @param {string=} opt_sourceText The optionally source text to evaluate
1105 * @return {boolean} True if the script was imported, false otherwise.
1106 * @private
1107 */
1108 goog.writeScriptTag_ = function(src, opt_sourceText) {
1109 if (goog.inHtmlDocument_()) {
1110 var doc = goog.global.document;
1111
1112 // If the user tries to require a new symbol after document load,
1113 // something has gone terribly wrong. Doing a document.write would
1114 // wipe out the page.
1115 if (doc.readyState == 'complete') {
1116 // Certain test frameworks load base.js multiple times, which tries
1117 // to write deps.js each time. If that happens, just fail silently.
1118 // These frameworks wipe the page between each load of base.js, so this
1119 // is OK.
1120 var isDeps = /\bdeps.js$/.test(src);
1121 if (isDeps) {
1122 return false;
1123 } else {
1124 throw Error('Cannot write "' + src + '" after document load');
1125 }
1126 }
1127
1128 var isOldIE = goog.IS_OLD_IE_;
1129
1130 if (opt_sourceText === undefined) {
1131 if (!isOldIE) {
1132 doc.write(
1133 '<script type="text/javascript" src="' +
1134 src + '"></' + 'script>');
1135 } else {
1136 var state = " onreadystatechange='goog.onScriptLoad_(this, " +
1137 ++goog.lastNonModuleScriptIndex_ + ")' ";
1138 doc.write(
1139 '<script type="text/javascript" src="' +
1140 src + '"' + state + '></' + 'script>');
1141 }
1142 } else {
1143 doc.write(
1144 '<script type="text/javascript">' +
1145 opt_sourceText +
1146 '</' + 'script>');
1147 }
1148 return true;
1149 } else {
1150 return false;
1151 }
1152 };
1153
1154
1155 /** @private {number} */
1156 goog.lastNonModuleScriptIndex_ = 0;
1157
1158
1159 /**
1160 * A readystatechange handler for legacy IE
1161 * @param {!HTMLScriptElement} script
1162 * @param {number} scriptIndex
1163 * @return {boolean}
1164 * @private
1165 */
1166 goog.onScriptLoad_ = function(script, scriptIndex) {
1167 // for now load the modules when we reach the last script,
1168 // later allow more inter-mingling.
1169 if (script.readyState == 'complete' &&
1170 goog.lastNonModuleScriptIndex_ == scriptIndex) {
1171 goog.loadQueuedModules_();
1172 }
1173 return true;
1174 };
1175
1176 /**
1177 * Resolves dependencies based on the dependencies added using addDependency
1178 * and calls importScript_ in the correct order.
1179 * @private
1180 */
1181 goog.writeScripts_ = function() {
1182 /** @type {!Array<string>} The scripts we need to write this time. */
1183 var scripts = [];
1184 var seenScript = {};
1185 var deps = goog.dependencies_;
1186
1187 /** @param {string} path */
1188 function visitNode(path) {
1189 if (path in deps.written) {
1190 return;
1191 }
1192
1193 // We have already visited this one. We can get here if we have cyclic
1194 // dependencies.
1195 if (path in deps.visited) {
1196 if (!(path in seenScript)) {
1197 seenScript[path] = true;
1198 scripts.push(path);
1199 }
1200 return;
1201 }
1202
1203 deps.visited[path] = true;
1204
1205 if (path in deps.requires) {
1206 for (var requireName in deps.requires[path]) {
1207 // If the required name is defined, we assume that it was already
1208 // bootstrapped by other means.
1209 if (!goog.isProvided_(requireName)) {
1210 if (requireName in deps.nameToPath) {
1211 visitNode(deps.nameToPath[requireName]);
1212 } else {
1213 throw Error('Undefined nameToPath for ' + requireName);
1214 }
1215 }
1216 }
1217 }
1218
1219 if (!(path in seenScript)) {
1220 seenScript[path] = true;
1221 scripts.push(path);
1222 }
1223 }
1224
1225 for (var path in goog.included_) {
1226 if (!deps.written[path]) {
1227 visitNode(path);
1228 }
1229 }
1230
1231 // record that we are going to load all these scripts.
1232 for (var i = 0; i < scripts.length; i++) {
1233 var path = scripts[i];
1234 goog.dependencies_.written[path] = true;
1235 }
1236
1237 // If a module is loaded synchronously then we need to
1238 // clear the current inModuleLoader value, and restore it when we are
1239 // done loading the current "requires".
1240 var moduleState = goog.moduleLoaderState_;
1241 goog.moduleLoaderState_ = null;
1242
1243 var loadingModule = false;
1244 for (var i = 0; i < scripts.length; i++) {
1245 var path = scripts[i];
1246 if (path) {
1247 if (!deps.pathIsModule[path]) {
1248 goog.importScript_(goog.basePath + path);
1249 } else {
1250 loadingModule = true;
1251 goog.importModule_(goog.basePath + path);
1252 }
1253 } else {
1254 goog.moduleLoaderState_ = moduleState;
1255 throw Error('Undefined script input');
1256 }
1257 }
1258
1259 // restore the current "module loading state"
1260 goog.moduleLoaderState_ = moduleState;
1261 };
1262
1263
1264 /**
1265 * Looks at the dependency rules and tries to determine the script file that
1266 * fulfills a particular rule.
1267 * @param {string} rule In the form goog.namespace.Class or project.script.
1268 * @return {?string} Url corresponding to the rule, or null.
1269 * @private
1270 */
1271 goog.getPathFromDeps_ = function(rule) {
1272 if (rule in goog.dependencies_.nameToPath) {
1273 return goog.dependencies_.nameToPath[rule];
1274 } else {
1275 return null;
1276 }
1277 };
1278
1279 goog.findBasePath_();
1280
1281 // Allow projects to manage the deps files themselves.
1282 if (!goog.global.CLOSURE_NO_DEPS) {
1283 goog.importScript_(goog.basePath + 'deps.js');
1284 }
1285}
1286
1287
1288/**
1289 * Normalize a file path by removing redundant ".." and extraneous "." file
1290 * path components.
1291 * @param {string} path
1292 * @return {string}
1293 * @private
1294 */
1295goog.normalizePath_ = function(path) {
1296 var components = path.split('/');
1297 var i = 0;
1298 while (i < components.length) {
1299 if (components[i] == '.') {
1300 components.splice(i, 1);
1301 } else if (i && components[i] == '..' &&
1302 components[i - 1] && components[i - 1] != '..') {
1303 components.splice(--i, 2);
1304 } else {
1305 i++;
1306 }
1307 }
1308 return components.join('/');
1309};
1310
1311
1312/**
1313 * Retrieve and execute a module.
1314 * @param {string} src Script source URL.
1315 * @private
1316 */
1317goog.retrieveAndExecModule_ = function(src) {
1318 if (!COMPILED) {
1319 // The full but non-canonicalized URL for later use.
1320 var originalPath = src;
1321 // Canonicalize the path, removing any /./ or /../ since Chrome's debugging
1322 // console doesn't auto-canonicalize XHR loads as it does <script> srcs.
1323 src = goog.normalizePath_(src);
1324
1325 var importScript = goog.global.CLOSURE_IMPORT_SCRIPT ||
1326 goog.writeScriptTag_;
1327
1328 var scriptText = null;
1329
1330 var xhr = new goog.global['XMLHttpRequest']();
1331
1332 /** @this {Object} */
1333 xhr.onload = function() {
1334 scriptText = this.responseText;
1335 };
1336 xhr.open('get', src, false);
1337 xhr.send();
1338
1339 scriptText = xhr.responseText;
1340
1341 if (scriptText != null) {
1342 var execModuleScript = goog.wrapModule_(src, scriptText);
1343 var isOldIE = goog.IS_OLD_IE_;
1344 if (isOldIE) {
1345 goog.dependencies_.deferred[originalPath] = execModuleScript;
1346 goog.queuedModules_.push(originalPath);
1347 } else {
1348 importScript(src, execModuleScript);
1349 }
1350 } else {
1351 throw new Error('load of ' + src + 'failed');
1352 }
1353 }
1354};
1355
1356
1357//==============================================================================
1358// Language Enhancements
1359//==============================================================================
1360
1361
1362/**
1363 * This is a "fixed" version of the typeof operator. It differs from the typeof
1364 * operator in such a way that null returns 'null' and arrays return 'array'.
1365 * @param {*} value The value to get the type of.
1366 * @return {string} The name of the type.
1367 */
1368goog.typeOf = function(value) {
1369 var s = typeof value;
1370 if (s == 'object') {
1371 if (value) {
1372 // Check these first, so we can avoid calling Object.prototype.toString if
1373 // possible.
1374 //
1375 // IE improperly marshals tyepof across execution contexts, but a
1376 // cross-context object will still return false for "instanceof Object".
1377 if (value instanceof Array) {
1378 return 'array';
1379 } else if (value instanceof Object) {
1380 return s;
1381 }
1382
1383 // HACK: In order to use an Object prototype method on the arbitrary
1384 // value, the compiler requires the value be cast to type Object,
1385 // even though the ECMA spec explicitly allows it.
1386 var className = Object.prototype.toString.call(
1387 /** @type {Object} */ (value));
1388 // In Firefox 3.6, attempting to access iframe window objects' length
1389 // property throws an NS_ERROR_FAILURE, so we need to special-case it
1390 // here.
1391 if (className == '[object Window]') {
1392 return 'object';
1393 }
1394
1395 // We cannot always use constructor == Array or instanceof Array because
1396 // different frames have different Array objects. In IE6, if the iframe
1397 // where the array was created is destroyed, the array loses its
1398 // prototype. Then dereferencing val.splice here throws an exception, so
1399 // we can't use goog.isFunction. Calling typeof directly returns 'unknown'
1400 // so that will work. In this case, this function will return false and
1401 // most array functions will still work because the array is still
1402 // array-like (supports length and []) even though it has lost its
1403 // prototype.
1404 // Mark Miller noticed that Object.prototype.toString
1405 // allows access to the unforgeable [[Class]] property.
1406 // 15.2.4.2 Object.prototype.toString ( )
1407 // When the toString method is called, the following steps are taken:
1408 // 1. Get the [[Class]] property of this object.
1409 // 2. Compute a string value by concatenating the three strings
1410 // "[object ", Result(1), and "]".
1411 // 3. Return Result(2).
1412 // and this behavior survives the destruction of the execution context.
1413 if ((className == '[object Array]' ||
1414 // In IE all non value types are wrapped as objects across window
1415 // boundaries (not iframe though) so we have to do object detection
1416 // for this edge case.
1417 typeof value.length == 'number' &&
1418 typeof value.splice != 'undefined' &&
1419 typeof value.propertyIsEnumerable != 'undefined' &&
1420 !value.propertyIsEnumerable('splice')
1421
1422 )) {
1423 return 'array';
1424 }
1425 // HACK: There is still an array case that fails.
1426 // function ArrayImpostor() {}
1427 // ArrayImpostor.prototype = [];
1428 // var impostor = new ArrayImpostor;
1429 // this can be fixed by getting rid of the fast path
1430 // (value instanceof Array) and solely relying on
1431 // (value && Object.prototype.toString.vall(value) === '[object Array]')
1432 // but that would require many more function calls and is not warranted
1433 // unless closure code is receiving objects from untrusted sources.
1434
1435 // IE in cross-window calls does not correctly marshal the function type
1436 // (it appears just as an object) so we cannot use just typeof val ==
1437 // 'function'. However, if the object has a call property, it is a
1438 // function.
1439 if ((className == '[object Function]' ||
1440 typeof value.call != 'undefined' &&
1441 typeof value.propertyIsEnumerable != 'undefined' &&
1442 !value.propertyIsEnumerable('call'))) {
1443 return 'function';
1444 }
1445
1446 } else {
1447 return 'null';
1448 }
1449
1450 } else if (s == 'function' && typeof value.call == 'undefined') {
1451 // In Safari typeof nodeList returns 'function', and on Firefox typeof
1452 // behaves similarly for HTML{Applet,Embed,Object}, Elements and RegExps. We
1453 // would like to return object for those and we can detect an invalid
1454 // function by making sure that the function object has a call method.
1455 return 'object';
1456 }
1457 return s;
1458};
1459
1460
1461/**
1462 * Returns true if the specified value is null.
1463 * @param {?} val Variable to test.
1464 * @return {boolean} Whether variable is null.
1465 */
1466goog.isNull = function(val) {
1467 return val === null;
1468};
1469
1470
1471/**
1472 * Returns true if the specified value is defined and not null.
1473 * @param {?} val Variable to test.
1474 * @return {boolean} Whether variable is defined and not null.
1475 */
1476goog.isDefAndNotNull = function(val) {
1477 // Note that undefined == null.
1478 return val != null;
1479};
1480
1481
1482/**
1483 * Returns true if the specified value is an array.
1484 * @param {?} val Variable to test.
1485 * @return {boolean} Whether variable is an array.
1486 */
1487goog.isArray = function(val) {
1488 return goog.typeOf(val) == 'array';
1489};
1490
1491
1492/**
1493 * Returns true if the object looks like an array. To qualify as array like
1494 * the value needs to be either a NodeList or an object with a Number length
1495 * property. As a special case, a function value is not array like, because its
1496 * length property is fixed to correspond to the number of expected arguments.
1497 * @param {?} val Variable to test.
1498 * @return {boolean} Whether variable is an array.
1499 */
1500goog.isArrayLike = function(val) {
1501 var type = goog.typeOf(val);
1502 // We do not use goog.isObject here in order to exclude function values.
1503 return type == 'array' || type == 'object' && typeof val.length == 'number';
1504};
1505
1506
1507/**
1508 * Returns true if the object looks like a Date. To qualify as Date-like the
1509 * value needs to be an object and have a getFullYear() function.
1510 * @param {?} val Variable to test.
1511 * @return {boolean} Whether variable is a like a Date.
1512 */
1513goog.isDateLike = function(val) {
1514 return goog.isObject(val) && typeof val.getFullYear == 'function';
1515};
1516
1517
1518/**
1519 * Returns true if the specified value is a string.
1520 * @param {?} val Variable to test.
1521 * @return {boolean} Whether variable is a string.
1522 */
1523goog.isString = function(val) {
1524 return typeof val == 'string';
1525};
1526
1527
1528/**
1529 * Returns true if the specified value is a boolean.
1530 * @param {?} val Variable to test.
1531 * @return {boolean} Whether variable is boolean.
1532 */
1533goog.isBoolean = function(val) {
1534 return typeof val == 'boolean';
1535};
1536
1537
1538/**
1539 * Returns true if the specified value is a number.
1540 * @param {?} val Variable to test.
1541 * @return {boolean} Whether variable is a number.
1542 */
1543goog.isNumber = function(val) {
1544 return typeof val == 'number';
1545};
1546
1547
1548/**
1549 * Returns true if the specified value is a function.
1550 * @param {?} val Variable to test.
1551 * @return {boolean} Whether variable is a function.
1552 */
1553goog.isFunction = function(val) {
1554 return goog.typeOf(val) == 'function';
1555};
1556
1557
1558/**
1559 * Returns true if the specified value is an object. This includes arrays and
1560 * functions.
1561 * @param {?} val Variable to test.
1562 * @return {boolean} Whether variable is an object.
1563 */
1564goog.isObject = function(val) {
1565 var type = typeof val;
1566 return type == 'object' && val != null || type == 'function';
1567 // return Object(val) === val also works, but is slower, especially if val is
1568 // not an object.
1569};
1570
1571
1572/**
1573 * Gets a unique ID for an object. This mutates the object so that further calls
1574 * with the same object as a parameter returns the same value. The unique ID is
1575 * guaranteed to be unique across the current session amongst objects that are
1576 * passed into {@code getUid}. There is no guarantee that the ID is unique or
1577 * consistent across sessions. It is unsafe to generate unique ID for function
1578 * prototypes.
1579 *
1580 * @param {Object} obj The object to get the unique ID for.
1581 * @return {number} The unique ID for the object.
1582 */
1583goog.getUid = function(obj) {
1584 // TODO(arv): Make the type stricter, do not accept null.
1585
1586 // In Opera window.hasOwnProperty exists but always returns false so we avoid
1587 // using it. As a consequence the unique ID generated for BaseClass.prototype
1588 // and SubClass.prototype will be the same.
1589 return obj[goog.UID_PROPERTY_] ||
1590 (obj[goog.UID_PROPERTY_] = ++goog.uidCounter_);
1591};
1592
1593
1594/**
1595 * Whether the given object is alreay assigned a unique ID.
1596 *
1597 * This does not modify the object.
1598 *
1599 * @param {!Object} obj The object to check.
1600 * @return {boolean} Whether there an assigned unique id for the object.
1601 */
1602goog.hasUid = function(obj) {
1603 return !!obj[goog.UID_PROPERTY_];
1604};
1605
1606
1607/**
1608 * Removes the unique ID from an object. This is useful if the object was
1609 * previously mutated using {@code goog.getUid} in which case the mutation is
1610 * undone.
1611 * @param {Object} obj The object to remove the unique ID field from.
1612 */
1613goog.removeUid = function(obj) {
1614 // TODO(arv): Make the type stricter, do not accept null.
1615
1616 // In IE, DOM nodes are not instances of Object and throw an exception if we
1617 // try to delete. Instead we try to use removeAttribute.
1618 if ('removeAttribute' in obj) {
1619 obj.removeAttribute(goog.UID_PROPERTY_);
1620 }
1621 /** @preserveTry */
1622 try {
1623 delete obj[goog.UID_PROPERTY_];
1624 } catch (ex) {
1625 }
1626};
1627
1628
1629/**
1630 * Name for unique ID property. Initialized in a way to help avoid collisions
1631 * with other closure JavaScript on the same page.
1632 * @type {string}
1633 * @private
1634 */
1635goog.UID_PROPERTY_ = 'closure_uid_' + ((Math.random() * 1e9) >>> 0);
1636
1637
1638/**
1639 * Counter for UID.
1640 * @type {number}
1641 * @private
1642 */
1643goog.uidCounter_ = 0;
1644
1645
1646/**
1647 * Adds a hash code field to an object. The hash code is unique for the
1648 * given object.
1649 * @param {Object} obj The object to get the hash code for.
1650 * @return {number} The hash code for the object.
1651 * @deprecated Use goog.getUid instead.
1652 */
1653goog.getHashCode = goog.getUid;
1654
1655
1656/**
1657 * Removes the hash code field from an object.
1658 * @param {Object} obj The object to remove the field from.
1659 * @deprecated Use goog.removeUid instead.
1660 */
1661goog.removeHashCode = goog.removeUid;
1662
1663
1664/**
1665 * Clones a value. The input may be an Object, Array, or basic type. Objects and
1666 * arrays will be cloned recursively.
1667 *
1668 * WARNINGS:
1669 * <code>goog.cloneObject</code> does not detect reference loops. Objects that
1670 * refer to themselves will cause infinite recursion.
1671 *
1672 * <code>goog.cloneObject</code> is unaware of unique identifiers, and copies
1673 * UIDs created by <code>getUid</code> into cloned results.
1674 *
1675 * @param {*} obj The value to clone.
1676 * @return {*} A clone of the input value.
1677 * @deprecated goog.cloneObject is unsafe. Prefer the goog.object methods.
1678 */
1679goog.cloneObject = function(obj) {
1680 var type = goog.typeOf(obj);
1681 if (type == 'object' || type == 'array') {
1682 if (obj.clone) {
1683 return obj.clone();
1684 }
1685 var clone = type == 'array' ? [] : {};
1686 for (var key in obj) {
1687 clone[key] = goog.cloneObject(obj[key]);
1688 }
1689 return clone;
1690 }
1691
1692 return obj;
1693};
1694
1695
1696/**
1697 * A native implementation of goog.bind.
1698 * @param {Function} fn A function to partially apply.
1699 * @param {Object|undefined} selfObj Specifies the object which this should
1700 * point to when the function is run.
1701 * @param {...*} var_args Additional arguments that are partially applied to the
1702 * function.
1703 * @return {!Function} A partially-applied form of the function bind() was
1704 * invoked as a method of.
1705 * @private
1706 * @suppress {deprecated} The compiler thinks that Function.prototype.bind is
1707 * deprecated because some people have declared a pure-JS version.
1708 * Only the pure-JS version is truly deprecated.
1709 */
1710goog.bindNative_ = function(fn, selfObj, var_args) {
1711 return /** @type {!Function} */ (fn.call.apply(fn.bind, arguments));
1712};
1713
1714
1715/**
1716 * A pure-JS implementation of goog.bind.
1717 * @param {Function} fn A function to partially apply.
1718 * @param {Object|undefined} selfObj Specifies the object which this should
1719 * point to when the function is run.
1720 * @param {...*} var_args Additional arguments that are partially applied to the
1721 * function.
1722 * @return {!Function} A partially-applied form of the function bind() was
1723 * invoked as a method of.
1724 * @private
1725 */
1726goog.bindJs_ = function(fn, selfObj, var_args) {
1727 if (!fn) {
1728 throw new Error();
1729 }
1730
1731 if (arguments.length > 2) {
1732 var boundArgs = Array.prototype.slice.call(arguments, 2);
1733 return function() {
1734 // Prepend the bound arguments to the current arguments.
1735 var newArgs = Array.prototype.slice.call(arguments);
1736 Array.prototype.unshift.apply(newArgs, boundArgs);
1737 return fn.apply(selfObj, newArgs);
1738 };
1739
1740 } else {
1741 return function() {
1742 return fn.apply(selfObj, arguments);
1743 };
1744 }
1745};
1746
1747
1748/**
1749 * Partially applies this function to a particular 'this object' and zero or
1750 * more arguments. The result is a new function with some arguments of the first
1751 * function pre-filled and the value of this 'pre-specified'.
1752 *
1753 * Remaining arguments specified at call-time are appended to the pre-specified
1754 * ones.
1755 *
1756 * Also see: {@link #partial}.
1757 *
1758 * Usage:
1759 * <pre>var barMethBound = bind(myFunction, myObj, 'arg1', 'arg2');
1760 * barMethBound('arg3', 'arg4');</pre>
1761 *
1762 * @param {?function(this:T, ...)} fn A function to partially apply.
1763 * @param {T} selfObj Specifies the object which this should point to when the
1764 * function is run.
1765 * @param {...*} var_args Additional arguments that are partially applied to the
1766 * function.
1767 * @return {!Function} A partially-applied form of the function bind() was
1768 * invoked as a method of.
1769 * @template T
1770 * @suppress {deprecated} See above.
1771 */
1772goog.bind = function(fn, selfObj, var_args) {
1773 // TODO(nicksantos): narrow the type signature.
1774 if (Function.prototype.bind &&
1775 // NOTE(nicksantos): Somebody pulled base.js into the default Chrome
1776 // extension environment. This means that for Chrome extensions, they get
1777 // the implementation of Function.prototype.bind that calls goog.bind
1778 // instead of the native one. Even worse, we don't want to introduce a
1779 // circular dependency between goog.bind and Function.prototype.bind, so
1780 // we have to hack this to make sure it works correctly.
1781 Function.prototype.bind.toString().indexOf('native code') != -1) {
1782 goog.bind = goog.bindNative_;
1783 } else {
1784 goog.bind = goog.bindJs_;
1785 }
1786 return goog.bind.apply(null, arguments);
1787};
1788
1789
1790/**
1791 * Like bind(), except that a 'this object' is not required. Useful when the
1792 * target function is already bound.
1793 *
1794 * Usage:
1795 * var g = partial(f, arg1, arg2);
1796 * g(arg3, arg4);
1797 *
1798 * @param {Function} fn A function to partially apply.
1799 * @param {...*} var_args Additional arguments that are partially applied to fn.
1800 * @return {!Function} A partially-applied form of the function bind() was
1801 * invoked as a method of.
1802 */
1803goog.partial = function(fn, var_args) {
1804 var args = Array.prototype.slice.call(arguments, 1);
1805 return function() {
1806 // Clone the array (with slice()) and append additional arguments
1807 // to the existing arguments.
1808 var newArgs = args.slice();
1809 newArgs.push.apply(newArgs, arguments);
1810 return fn.apply(this, newArgs);
1811 };
1812};
1813
1814
1815/**
1816 * Copies all the members of a source object to a target object. This method
1817 * does not work on all browsers for all objects that contain keys such as
1818 * toString or hasOwnProperty. Use goog.object.extend for this purpose.
1819 * @param {Object} target Target.
1820 * @param {Object} source Source.
1821 */
1822goog.mixin = function(target, source) {
1823 for (var x in source) {
1824 target[x] = source[x];
1825 }
1826
1827 // For IE7 or lower, the for-in-loop does not contain any properties that are
1828 // not enumerable on the prototype object (for example, isPrototypeOf from
1829 // Object.prototype) but also it will not include 'replace' on objects that
1830 // extend String and change 'replace' (not that it is common for anyone to
1831 // extend anything except Object).
1832};
1833
1834
1835/**
1836 * @return {number} An integer value representing the number of milliseconds
1837 * between midnight, January 1, 1970 and the current time.
1838 */
1839goog.now = (goog.TRUSTED_SITE && Date.now) || (function() {
1840 // Unary plus operator converts its operand to a number which in the case of
1841 // a date is done by calling getTime().
1842 return +new Date();
1843});
1844
1845
1846/**
1847 * Evals JavaScript in the global scope. In IE this uses execScript, other
1848 * browsers use goog.global.eval. If goog.global.eval does not evaluate in the
1849 * global scope (for example, in Safari), appends a script tag instead.
1850 * Throws an exception if neither execScript or eval is defined.
1851 * @param {string} script JavaScript string.
1852 */
1853goog.globalEval = function(script) {
1854 if (goog.global.execScript) {
1855 goog.global.execScript(script, 'JavaScript');
1856 } else if (goog.global.eval) {
1857 // Test to see if eval works
1858 if (goog.evalWorksForGlobals_ == null) {
1859 goog.global.eval('var _et_ = 1;');
1860 if (typeof goog.global['_et_'] != 'undefined') {
1861 delete goog.global['_et_'];
1862 goog.evalWorksForGlobals_ = true;
1863 } else {
1864 goog.evalWorksForGlobals_ = false;
1865 }
1866 }
1867
1868 if (goog.evalWorksForGlobals_) {
1869 goog.global.eval(script);
1870 } else {
1871 var doc = goog.global.document;
1872 var scriptElt = doc.createElement('script');
1873 scriptElt.type = 'text/javascript';
1874 scriptElt.defer = false;
1875 // Note(user): can't use .innerHTML since "t('<test>')" will fail and
1876 // .text doesn't work in Safari 2. Therefore we append a text node.
1877 scriptElt.appendChild(doc.createTextNode(script));
1878 doc.body.appendChild(scriptElt);
1879 doc.body.removeChild(scriptElt);
1880 }
1881 } else {
1882 throw Error('goog.globalEval not available');
1883 }
1884};
1885
1886
1887/**
1888 * Indicates whether or not we can call 'eval' directly to eval code in the
1889 * global scope. Set to a Boolean by the first call to goog.globalEval (which
1890 * empirically tests whether eval works for globals). @see goog.globalEval
1891 * @type {?boolean}
1892 * @private
1893 */
1894goog.evalWorksForGlobals_ = null;
1895
1896
1897/**
1898 * Optional map of CSS class names to obfuscated names used with
1899 * goog.getCssName().
1900 * @private {!Object<string, string>|undefined}
1901 * @see goog.setCssNameMapping
1902 */
1903goog.cssNameMapping_;
1904
1905
1906/**
1907 * Optional obfuscation style for CSS class names. Should be set to either
1908 * 'BY_WHOLE' or 'BY_PART' if defined.
1909 * @type {string|undefined}
1910 * @private
1911 * @see goog.setCssNameMapping
1912 */
1913goog.cssNameMappingStyle_;
1914
1915
1916/**
1917 * Handles strings that are intended to be used as CSS class names.
1918 *
1919 * This function works in tandem with @see goog.setCssNameMapping.
1920 *
1921 * Without any mapping set, the arguments are simple joined with a hyphen and
1922 * passed through unaltered.
1923 *
1924 * When there is a mapping, there are two possible styles in which these
1925 * mappings are used. In the BY_PART style, each part (i.e. in between hyphens)
1926 * of the passed in css name is rewritten according to the map. In the BY_WHOLE
1927 * style, the full css name is looked up in the map directly. If a rewrite is
1928 * not specified by the map, the compiler will output a warning.
1929 *
1930 * When the mapping is passed to the compiler, it will replace calls to
1931 * goog.getCssName with the strings from the mapping, e.g.
1932 * var x = goog.getCssName('foo');
1933 * var y = goog.getCssName(this.baseClass, 'active');
1934 * becomes:
1935 * var x= 'foo';
1936 * var y = this.baseClass + '-active';
1937 *
1938 * If one argument is passed it will be processed, if two are passed only the
1939 * modifier will be processed, as it is assumed the first argument was generated
1940 * as a result of calling goog.getCssName.
1941 *
1942 * @param {string} className The class name.
1943 * @param {string=} opt_modifier A modifier to be appended to the class name.
1944 * @return {string} The class name or the concatenation of the class name and
1945 * the modifier.
1946 */
1947goog.getCssName = function(className, opt_modifier) {
1948 var getMapping = function(cssName) {
1949 return goog.cssNameMapping_[cssName] || cssName;
1950 };
1951
1952 var renameByParts = function(cssName) {
1953 // Remap all the parts individually.
1954 var parts = cssName.split('-');
1955 var mapped = [];
1956 for (var i = 0; i < parts.length; i++) {
1957 mapped.push(getMapping(parts[i]));
1958 }
1959 return mapped.join('-');
1960 };
1961
1962 var rename;
1963 if (goog.cssNameMapping_) {
1964 rename = goog.cssNameMappingStyle_ == 'BY_WHOLE' ?
1965 getMapping : renameByParts;
1966 } else {
1967 rename = function(a) {
1968 return a;
1969 };
1970 }
1971
1972 if (opt_modifier) {
1973 return className + '-' + rename(opt_modifier);
1974 } else {
1975 return rename(className);
1976 }
1977};
1978
1979
1980/**
1981 * Sets the map to check when returning a value from goog.getCssName(). Example:
1982 * <pre>
1983 * goog.setCssNameMapping({
1984 * "goog": "a",
1985 * "disabled": "b",
1986 * });
1987 *
1988 * var x = goog.getCssName('goog');
1989 * // The following evaluates to: "a a-b".
1990 * goog.getCssName('goog') + ' ' + goog.getCssName(x, 'disabled')
1991 * </pre>
1992 * When declared as a map of string literals to string literals, the JSCompiler
1993 * will replace all calls to goog.getCssName() using the supplied map if the
1994 * --closure_pass flag is set.
1995 *
1996 * @param {!Object} mapping A map of strings to strings where keys are possible
1997 * arguments to goog.getCssName() and values are the corresponding values
1998 * that should be returned.
1999 * @param {string=} opt_style The style of css name mapping. There are two valid
2000 * options: 'BY_PART', and 'BY_WHOLE'.
2001 * @see goog.getCssName for a description.
2002 */
2003goog.setCssNameMapping = function(mapping, opt_style) {
2004 goog.cssNameMapping_ = mapping;
2005 goog.cssNameMappingStyle_ = opt_style;
2006};
2007
2008
2009/**
2010 * To use CSS renaming in compiled mode, one of the input files should have a
2011 * call to goog.setCssNameMapping() with an object literal that the JSCompiler
2012 * can extract and use to replace all calls to goog.getCssName(). In uncompiled
2013 * mode, JavaScript code should be loaded before this base.js file that declares
2014 * a global variable, CLOSURE_CSS_NAME_MAPPING, which is used below. This is
2015 * to ensure that the mapping is loaded before any calls to goog.getCssName()
2016 * are made in uncompiled mode.
2017 *
2018 * A hook for overriding the CSS name mapping.
2019 * @type {!Object<string, string>|undefined}
2020 */
2021goog.global.CLOSURE_CSS_NAME_MAPPING;
2022
2023
2024if (!COMPILED && goog.global.CLOSURE_CSS_NAME_MAPPING) {
2025 // This does not call goog.setCssNameMapping() because the JSCompiler
2026 // requires that goog.setCssNameMapping() be called with an object literal.
2027 goog.cssNameMapping_ = goog.global.CLOSURE_CSS_NAME_MAPPING;
2028}
2029
2030
2031/**
2032 * Gets a localized message.
2033 *
2034 * This function is a compiler primitive. If you give the compiler a localized
2035 * message bundle, it will replace the string at compile-time with a localized
2036 * version, and expand goog.getMsg call to a concatenated string.
2037 *
2038 * Messages must be initialized in the form:
2039 * <code>
2040 * var MSG_NAME = goog.getMsg('Hello {$placeholder}', {'placeholder': 'world'});
2041 * </code>
2042 *
2043 * @param {string} str Translatable string, places holders in the form {$foo}.
2044 * @param {Object<string, string>=} opt_values Maps place holder name to value.
2045 * @return {string} message with placeholders filled.
2046 */
2047goog.getMsg = function(str, opt_values) {
2048 if (opt_values) {
2049 str = str.replace(/\{\$([^}]+)}/g, function(match, key) {
2050 return key in opt_values ? opt_values[key] : match;
2051 });
2052 }
2053 return str;
2054};
2055
2056
2057/**
2058 * Gets a localized message. If the message does not have a translation, gives a
2059 * fallback message.
2060 *
2061 * This is useful when introducing a new message that has not yet been
2062 * translated into all languages.
2063 *
2064 * This function is a compiler primitive. Must be used in the form:
2065 * <code>var x = goog.getMsgWithFallback(MSG_A, MSG_B);</code>
2066 * where MSG_A and MSG_B were initialized with goog.getMsg.
2067 *
2068 * @param {string} a The preferred message.
2069 * @param {string} b The fallback message.
2070 * @return {string} The best translated message.
2071 */
2072goog.getMsgWithFallback = function(a, b) {
2073 return a;
2074};
2075
2076
2077/**
2078 * Exposes an unobfuscated global namespace path for the given object.
2079 * Note that fields of the exported object *will* be obfuscated, unless they are
2080 * exported in turn via this function or goog.exportProperty.
2081 *
2082 * Also handy for making public items that are defined in anonymous closures.
2083 *
2084 * ex. goog.exportSymbol('public.path.Foo', Foo);
2085 *
2086 * ex. goog.exportSymbol('public.path.Foo.staticFunction', Foo.staticFunction);
2087 * public.path.Foo.staticFunction();
2088 *
2089 * ex. goog.exportSymbol('public.path.Foo.prototype.myMethod',
2090 * Foo.prototype.myMethod);
2091 * new public.path.Foo().myMethod();
2092 *
2093 * @param {string} publicPath Unobfuscated name to export.
2094 * @param {*} object Object the name should point to.
2095 * @param {Object=} opt_objectToExportTo The object to add the path to; default
2096 * is goog.global.
2097 */
2098goog.exportSymbol = function(publicPath, object, opt_objectToExportTo) {
2099 goog.exportPath_(publicPath, object, opt_objectToExportTo);
2100};
2101
2102
2103/**
2104 * Exports a property unobfuscated into the object's namespace.
2105 * ex. goog.exportProperty(Foo, 'staticFunction', Foo.staticFunction);
2106 * ex. goog.exportProperty(Foo.prototype, 'myMethod', Foo.prototype.myMethod);
2107 * @param {Object} object Object whose static property is being exported.
2108 * @param {string} publicName Unobfuscated name to export.
2109 * @param {*} symbol Object the name should point to.
2110 */
2111goog.exportProperty = function(object, publicName, symbol) {
2112 object[publicName] = symbol;
2113};
2114
2115
2116/**
2117 * Inherit the prototype methods from one constructor into another.
2118 *
2119 * Usage:
2120 * <pre>
2121 * function ParentClass(a, b) { }
2122 * ParentClass.prototype.foo = function(a) { };
2123 *
2124 * function ChildClass(a, b, c) {
2125 * ChildClass.base(this, 'constructor', a, b);
2126 * }
2127 * goog.inherits(ChildClass, ParentClass);
2128 *
2129 * var child = new ChildClass('a', 'b', 'see');
2130 * child.foo(); // This works.
2131 * </pre>
2132 *
2133 * @param {Function} childCtor Child class.
2134 * @param {Function} parentCtor Parent class.
2135 */
2136goog.inherits = function(childCtor, parentCtor) {
2137 /** @constructor */
2138 function tempCtor() {};
2139 tempCtor.prototype = parentCtor.prototype;
2140 childCtor.superClass_ = parentCtor.prototype;
2141 childCtor.prototype = new tempCtor();
2142 /** @override */
2143 childCtor.prototype.constructor = childCtor;
2144
2145 /**
2146 * Calls superclass constructor/method.
2147 *
2148 * This function is only available if you use goog.inherits to
2149 * express inheritance relationships between classes.
2150 *
2151 * NOTE: This is a replacement for goog.base and for superClass_
2152 * property defined in childCtor.
2153 *
2154 * @param {!Object} me Should always be "this".
2155 * @param {string} methodName The method name to call. Calling
2156 * superclass constructor can be done with the special string
2157 * 'constructor'.
2158 * @param {...*} var_args The arguments to pass to superclass
2159 * method/constructor.
2160 * @return {*} The return value of the superclass method/constructor.
2161 */
2162 childCtor.base = function(me, methodName, var_args) {
2163 var args = Array.prototype.slice.call(arguments, 2);
2164 return parentCtor.prototype[methodName].apply(me, args);
2165 };
2166};
2167
2168
2169/**
2170 * Call up to the superclass.
2171 *
2172 * If this is called from a constructor, then this calls the superclass
2173 * constructor with arguments 1-N.
2174 *
2175 * If this is called from a prototype method, then you must pass the name of the
2176 * method as the second argument to this function. If you do not, you will get a
2177 * runtime error. This calls the superclass' method with arguments 2-N.
2178 *
2179 * This function only works if you use goog.inherits to express inheritance
2180 * relationships between your classes.
2181 *
2182 * This function is a compiler primitive. At compile-time, the compiler will do
2183 * macro expansion to remove a lot of the extra overhead that this function
2184 * introduces. The compiler will also enforce a lot of the assumptions that this
2185 * function makes, and treat it as a compiler error if you break them.
2186 *
2187 * @param {!Object} me Should always be "this".
2188 * @param {*=} opt_methodName The method name if calling a super method.
2189 * @param {...*} var_args The rest of the arguments.
2190 * @return {*} The return value of the superclass method.
2191 * @suppress {es5Strict} This method can not be used in strict mode, but
2192 * all Closure Library consumers must depend on this file.
2193 */
2194goog.base = function(me, opt_methodName, var_args) {
2195 var caller = arguments.callee.caller;
2196
2197 if (goog.STRICT_MODE_COMPATIBLE || (goog.DEBUG && !caller)) {
2198 throw Error('arguments.caller not defined. goog.base() cannot be used ' +
2199 'with strict mode code. See ' +
2200 'http://www.ecma-international.org/ecma-262/5.1/#sec-C');
2201 }
2202
2203 if (caller.superClass_) {
2204 // This is a constructor. Call the superclass constructor.
2205 return caller.superClass_.constructor.apply(
2206 me, Array.prototype.slice.call(arguments, 1));
2207 }
2208
2209 var args = Array.prototype.slice.call(arguments, 2);
2210 var foundCaller = false;
2211 for (var ctor = me.constructor;
2212 ctor; ctor = ctor.superClass_ && ctor.superClass_.constructor) {
2213 if (ctor.prototype[opt_methodName] === caller) {
2214 foundCaller = true;
2215 } else if (foundCaller) {
2216 return ctor.prototype[opt_methodName].apply(me, args);
2217 }
2218 }
2219
2220 // If we did not find the caller in the prototype chain, then one of two
2221 // things happened:
2222 // 1) The caller is an instance method.
2223 // 2) This method was not called by the right caller.
2224 if (me[opt_methodName] === caller) {
2225 return me.constructor.prototype[opt_methodName].apply(me, args);
2226 } else {
2227 throw Error(
2228 'goog.base called from a method of one name ' +
2229 'to a method of a different name');
2230 }
2231};
2232
2233
2234/**
2235 * Allow for aliasing within scope functions. This function exists for
2236 * uncompiled code - in compiled code the calls will be inlined and the aliases
2237 * applied. In uncompiled code the function is simply run since the aliases as
2238 * written are valid JavaScript.
2239 *
2240 *
2241 * @param {function()} fn Function to call. This function can contain aliases
2242 * to namespaces (e.g. "var dom = goog.dom") or classes
2243 * (e.g. "var Timer = goog.Timer").
2244 */
2245goog.scope = function(fn) {
2246 fn.call(goog.global);
2247};
2248
2249
2250/*
2251 * To support uncompiled, strict mode bundles that use eval to divide source
2252 * like so:
2253 * eval('someSource;//# sourceUrl sourcefile.js');
2254 * We need to export the globally defined symbols "goog" and "COMPILED".
2255 * Exporting "goog" breaks the compiler optimizations, so we required that
2256 * be defined externally.
2257 * NOTE: We don't use goog.exportSymbol here because we don't want to trigger
2258 * extern generation when that compiler option is enabled.
2259 */
2260if (!COMPILED) {
2261 goog.global['COMPILED'] = COMPILED;
2262}
2263
2264
2265
2266//==============================================================================
2267// goog.defineClass implementation
2268//==============================================================================
2269
2270
2271/**
2272 * Creates a restricted form of a Closure "class":
2273 * - from the compiler's perspective, the instance returned from the
2274 * constructor is sealed (no new properties may be added). This enables
2275 * better checks.
2276 * - the compiler will rewrite this definition to a form that is optimal
2277 * for type checking and optimization (initially this will be a more
2278 * traditional form).
2279 *
2280 * @param {Function} superClass The superclass, Object or null.
2281 * @param {goog.defineClass.ClassDescriptor} def
2282 * An object literal describing the
2283 * the class. It may have the following properties:
2284 * "constructor": the constructor function
2285 * "statics": an object literal containing methods to add to the constructor
2286 * as "static" methods or a function that will receive the constructor
2287 * function as its only parameter to which static properties can
2288 * be added.
2289 * all other properties are added to the prototype.
2290 * @return {!Function} The class constructor.
2291 */
2292goog.defineClass = function(superClass, def) {
2293 // TODO(johnlenz): consider making the superClass an optional parameter.
2294 var constructor = def.constructor;
2295 var statics = def.statics;
2296 // Wrap the constructor prior to setting up the prototype and static methods.
2297 if (!constructor || constructor == Object.prototype.constructor) {
2298 constructor = function() {
2299 throw Error('cannot instantiate an interface (no constructor defined).');
2300 };
2301 }
2302
2303 var cls = goog.defineClass.createSealingConstructor_(constructor, superClass);
2304 if (superClass) {
2305 goog.inherits(cls, superClass);
2306 }
2307
2308 // Remove all the properties that should not be copied to the prototype.
2309 delete def.constructor;
2310 delete def.statics;
2311
2312 goog.defineClass.applyProperties_(cls.prototype, def);
2313 if (statics != null) {
2314 if (statics instanceof Function) {
2315 statics(cls);
2316 } else {
2317 goog.defineClass.applyProperties_(cls, statics);
2318 }
2319 }
2320
2321 return cls;
2322};
2323
2324
2325/**
2326 * @typedef {
2327 * !Object|
2328 * {constructor:!Function}|
2329 * {constructor:!Function, statics:(Object|function(Function):void)}}
2330 */
2331goog.defineClass.ClassDescriptor;
2332
2333
2334/**
2335 * @define {boolean} Whether the instances returned by
2336 * goog.defineClass should be sealed when possible.
2337 */
2338goog.define('goog.defineClass.SEAL_CLASS_INSTANCES', goog.DEBUG);
2339
2340
2341/**
2342 * If goog.defineClass.SEAL_CLASS_INSTANCES is enabled and Object.seal is
2343 * defined, this function will wrap the constructor in a function that seals the
2344 * results of the provided constructor function.
2345 *
2346 * @param {!Function} ctr The constructor whose results maybe be sealed.
2347 * @param {Function} superClass The superclass constructor.
2348 * @return {!Function} The replacement constructor.
2349 * @private
2350 */
2351goog.defineClass.createSealingConstructor_ = function(ctr, superClass) {
2352 if (goog.defineClass.SEAL_CLASS_INSTANCES &&
2353 Object.seal instanceof Function) {
2354 // Don't seal subclasses of unsealable-tagged legacy classes.
2355 if (superClass && superClass.prototype &&
2356 superClass.prototype[goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_]) {
2357 return ctr;
2358 }
2359 /**
2360 * @this {*}
2361 * @return {?}
2362 */
2363 var wrappedCtr = function() {
2364 // Don't seal an instance of a subclass when it calls the constructor of
2365 // its super class as there is most likely still setup to do.
2366 var instance = ctr.apply(this, arguments) || this;
2367 instance[goog.UID_PROPERTY_] = instance[goog.UID_PROPERTY_];
2368 if (this.constructor === wrappedCtr) {
2369 Object.seal(instance);
2370 }
2371 return instance;
2372 };
2373 return wrappedCtr;
2374 }
2375 return ctr;
2376};
2377
2378
2379// TODO(johnlenz): share these values with the goog.object
2380/**
2381 * The names of the fields that are defined on Object.prototype.
2382 * @type {!Array<string>}
2383 * @private
2384 * @const
2385 */
2386goog.defineClass.OBJECT_PROTOTYPE_FIELDS_ = [
2387 'constructor',
2388 'hasOwnProperty',
2389 'isPrototypeOf',
2390 'propertyIsEnumerable',
2391 'toLocaleString',
2392 'toString',
2393 'valueOf'
2394];
2395
2396
2397// TODO(johnlenz): share this function with the goog.object
2398/**
2399 * @param {!Object} target The object to add properties to.
2400 * @param {!Object} source The object to copy properites from.
2401 * @private
2402 */
2403goog.defineClass.applyProperties_ = function(target, source) {
2404 // TODO(johnlenz): update this to support ES5 getters/setters
2405
2406 var key;
2407 for (key in source) {
2408 if (Object.prototype.hasOwnProperty.call(source, key)) {
2409 target[key] = source[key];
2410 }
2411 }
2412
2413 // For IE the for-in-loop does not contain any properties that are not
2414 // enumerable on the prototype object (for example isPrototypeOf from
2415 // Object.prototype) and it will also not include 'replace' on objects that
2416 // extend String and change 'replace' (not that it is common for anyone to
2417 // extend anything except Object).
2418 for (var i = 0; i < goog.defineClass.OBJECT_PROTOTYPE_FIELDS_.length; i++) {
2419 key = goog.defineClass.OBJECT_PROTOTYPE_FIELDS_[i];
2420 if (Object.prototype.hasOwnProperty.call(source, key)) {
2421 target[key] = source[key];
2422 }
2423 }
2424};
2425
2426
2427/**
2428 * Sealing classes breaks the older idiom of assigning properties on the
2429 * prototype rather than in the constructor. As such, goog.defineClass
2430 * must not seal subclasses of these old-style classes until they are fixed.
2431 * Until then, this marks a class as "broken", instructing defineClass
2432 * not to seal subclasses.
2433 * @param {!Function} ctr The legacy constructor to tag as unsealable.
2434 */
2435goog.tagUnsealableClass = function(ctr) {
2436 if (!COMPILED && goog.defineClass.SEAL_CLASS_INSTANCES) {
2437 ctr.prototype[goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_] = true;
2438 }
2439};
2440
2441
2442/**
2443 * Name for unsealable tag property.
2444 * @const @private {string}
2445 */
2446goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_ = 'goog_defineClass_legacy_unsealable';