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