├── README.md
├── analyze.js
├── analyze.py
├── jspanda.py
├── panda.gif
├── payload.js
├── pollute.png
├── testfiles
├── protopollution_closure.js
├── protopollution_freeze_test.html
├── protopollution_test.html
└── testfile
└── url.txt
/README.md:
--------------------------------------------------------------------------------
1 | # JSPanda
2 |
3 | [](https://www.youtube.com/watch?v=6At3qjurhOs)
4 |
5 | JSpanda is client-side prototype pollution vulnerability scanner. It has two key features, scanning vulnerability the supplied URLs and analyzing the JavaScript libraries' source code.
6 |
7 | However, JSpanda cannot detect advanced prototype pollution vulnerabilities.
8 |
9 | ## **How JSPanda works?**
10 |
11 | - Uses multiple payloads for prototype pollution vulnerability.
12 | - Gathers all the links in the targets for scanning and add payloads to JSpanda-obtained URLs, navigates to each URL with headless Chromedriver.
13 | - Scans all words in the source code of potentially vulnerable JavaScript library and it creates a simple JS PoC by finding the script gadget, helping you analyze the code manually.
14 |
15 | ## **Requirements**
16 |
17 | - Download latest version of Google Chrome and Chromedriver
18 | - Selenium
19 |
20 | ## **Usage**
21 |
22 | Scan: python3.7 jspanda.py
23 |
24 | - Add URLs to url.txt file, *for instance : example.com*
25 |
26 | Basic Source Code Analysis : python3.7 analyze.py
27 |
28 | - Add a JavaScript library's source code to analyze.js
29 | - Generate PoC code using analyze.py
30 | - Execute PoC code on Chrome's console. It pollutes all the words collected from the source code and show it on the screen. So it may generate false positive results. These outputs provide additional information to researchers, do not automate everything.
31 |
32 | ### Demonstration
33 |
34 | [](https://asciinema.org/a/BOazgAVyW6yHqhUE3fEYcCiML)
35 |
36 | ### Source code analysis - Screenshot
37 |
38 | 
39 |
40 | **Supporting Materials :**
41 |
42 | [https://twitter.com/har1sec/status/1314469278322655233](https://twitter.com/har1sec/status/1314469278322655233)
43 |
44 |
45 | [https://github.com/BlackFan/client-side-prototype-pollution](https://github.com/BlackFan/client-side-prototype-pollution)
46 |
47 |
48 | [https://github.com/ThePacketBender/notes/blob/01c0b834f6e3ee4d934b087b2d92c9e484dc2a50/web/prototype_pollution.txt](https://github.com/ThePacketBender/notes/blob/01c0b834f6e3ee4d934b087b2d92c9e484dc2a50/web/prototype_pollution.txt)
49 |
50 | [https://habr.com/ru/company/huawei/blog/547178/](https://habr.com/ru/company/huawei/blog/547178/)
51 |
52 | [https://infosecwriteups.com/javascript-prototype-pollution-practice-of-finding-and-exploitation-f97284333b2](https://infosecwriteups.com/javascript-prototype-pollution-practice-of-finding-and-exploitation-f97284333b2)
53 |
54 | [https://github.com/securitum/research/tree/master/r2020_prototype-pollution](https://github.com/securitum/research/tree/master/r2020_prototype-pollution)
55 |
56 |
57 | [Learn Prototype Pollution in Series - Part 2](https://attacker-codeninja.github.io/2021-07-05-Learn-Prototype-Pollution-Part-2/)
58 |
59 | [dwisiswant0/ppfuzz](https://github.com/dwisiswant0/ppfuzz)
60 |
61 | [GitHub - raverrr/plution: Prototype pollution scanner using headless chrome](https://github.com/raverrr/plution)
62 |
63 | [JavaScript Prototype Poisoning Vulnerabilities in the Wild](https://medium.com/intrinsic-blog/javascript-prototype-poisoning-vulnerabilities-in-the-wild-7bc15347c96)
64 |
65 | [The Complete Guide to Prototype Pollution Vulnerabilities](https://www.whitesourcesoftware.com/resources/blog/prototype-pollution-vulnerabilities/)
66 |
--------------------------------------------------------------------------------
/analyze.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright The Closure Library Authors.
4 | * SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * @fileoverview Bootstrap for the Google JS Library (Closure).
9 | *
10 | * In uncompiled mode base.js will attempt to load Closure's deps file, unless
11 | * the global CLOSURE_NO_DEPS
is set to true. This allows projects
12 | * to include their own deps file(s) from different locations.
13 | *
14 | * Avoid including base.js more than once. This is strictly discouraged and not
15 | * supported. goog.require(...) won't work properly in that case.
16 | *
17 | * @provideGoog
18 | */
19 |
20 |
21 | /**
22 | * @define {boolean} Overridden to true by the compiler.
23 | */
24 | var COMPILED = false;
25 |
26 |
27 | /**
28 | * Base namespace for the Closure library. Checks to see goog is already
29 | * defined in the current scope before assigning to prevent clobbering if
30 | * base.js is loaded more than once.
31 | *
32 | * @const
33 | */
34 | var goog = goog || {};
35 |
36 | /**
37 | * Reference to the global object.
38 | * https://www.ecma-international.org/ecma-262/9.0/index.html#sec-global-object
39 | *
40 | * More info on this implementation here:
41 | * https://docs.google.com/document/d/1NAeW4Wk7I7FV0Y2tcUFvQdGMc89k2vdgSXInw8_nvCI/edit
42 | *
43 | * @const
44 | * @suppress {undefinedVars} self won't be referenced unless `this` is falsy.
45 | * @type {!Global}
46 | */
47 | goog.global =
48 | // Check `this` first for backwards compatibility.
49 | // Valid unless running as an ES module or in a function wrapper called
50 | // without setting `this` properly.
51 | // Note that base.js can't usefully be imported as an ES module, but it may
52 | // be compiled into bundles that are loadable as ES modules.
53 | this ||
54 | // https://developer.mozilla.org/en-US/docs/Web/API/Window/self
55 | // For in-page browser environments and workers.
56 | self;
57 |
58 |
59 | /**
60 | * A hook for overriding the define values in uncompiled mode.
61 | *
62 | * In uncompiled mode, `CLOSURE_UNCOMPILED_DEFINES` may be defined before
63 | * loading base.js. If a key is defined in `CLOSURE_UNCOMPILED_DEFINES`,
64 | * `goog.define` will use the value instead of the default value. This
65 | * allows flags to be overwritten without compilation (this is normally
66 | * accomplished with the compiler's "define" flag).
67 | *
68 | * Example:
69 | *
70 | * var CLOSURE_UNCOMPILED_DEFINES = {'goog.DEBUG': false};
71 | *
72 | *
73 | * @type {Object|undefined}
74 | */
75 | goog.global.CLOSURE_UNCOMPILED_DEFINES;
76 |
77 |
78 | /**
79 | * A hook for overriding the define values in uncompiled or compiled mode,
80 | * like CLOSURE_UNCOMPILED_DEFINES but effective in compiled code. In
81 | * uncompiled code CLOSURE_UNCOMPILED_DEFINES takes precedence.
82 | *
83 | * Also unlike CLOSURE_UNCOMPILED_DEFINES the values must be number, boolean or
84 | * string literals or the compiler will emit an error.
85 | *
86 | * While any @define value may be set, only those set with goog.define will be
87 | * effective for uncompiled code.
88 | *
89 | * Example:
90 | *
91 | * var CLOSURE_DEFINES = {'goog.DEBUG': false} ;
92 | *
93 | *
94 | * @type {Object|undefined}
95 | */
96 | goog.global.CLOSURE_DEFINES;
97 |
98 |
99 | /**
100 | * Builds an object structure for the provided namespace path, ensuring that
101 | * names that already exist are not overwritten. For example:
102 | * "a.b.c" -> a = {};a.b={};a.b.c={};
103 | * Used by goog.provide and goog.exportSymbol.
104 | * @param {string} name The name of the object that this file defines.
105 | * @param {*=} object The object to expose at the end of the path.
106 | * @param {boolean=} overwriteImplicit If object is set and a previous call
107 | * implicitly constructed the namespace given by name, this parameter
108 | * controls whether object should overwrite the implicitly constructed
109 | * namespace or be merged into it. Defaults to false.
110 | * @param {?Object=} objectToExportTo The object to add the path to; if this
111 | * field is not specified, its value defaults to `goog.global`.
112 | * @private
113 | */
114 | goog.exportPath_ = function(name, object, overwriteImplicit, objectToExportTo) {
115 | var parts = name.split('.');
116 | var cur = objectToExportTo || goog.global;
117 |
118 | // Internet Explorer exhibits strange behavior when throwing errors from
119 | // methods externed in this manner. See the testExportSymbolExceptions in
120 | // base_test.html for an example.
121 | if (!(parts[0] in cur) && typeof cur.execScript != 'undefined') {
122 | cur.execScript('var ' + parts[0]);
123 | }
124 |
125 | for (var part; parts.length && (part = parts.shift());) {
126 | if (!parts.length && object !== undefined) {
127 | if (!overwriteImplicit && goog.isObject(object) &&
128 | goog.isObject(cur[part])) {
129 | // Merge properties on object (the input parameter) with the existing
130 | // implicitly defined namespace, so as to not clobber previously
131 | // defined child namespaces.
132 | for (var prop in object) {
133 | if (object.hasOwnProperty(prop)) {
134 | cur[part][prop] = object[prop];
135 | }
136 | }
137 | } else {
138 | // Either there is no existing implicit namespace, or overwriteImplicit
139 | // is set to true, so directly assign object (the input parameter) to
140 | // the namespace.
141 | cur[part] = object;
142 | }
143 | } else if (cur[part] && cur[part] !== Object.prototype[part]) {
144 | cur = cur[part];
145 | } else {
146 | cur = cur[part] = {};
147 | }
148 | }
149 | };
150 |
151 |
152 | /**
153 | * Defines a named value. In uncompiled mode, the value is retrieved from
154 | * CLOSURE_DEFINES or CLOSURE_UNCOMPILED_DEFINES if the object is defined and
155 | * has the property specified, and otherwise used the defined defaultValue.
156 | * When compiled the default can be overridden using the compiler options or the
157 | * value set in the CLOSURE_DEFINES object. Returns the defined value so that it
158 | * can be used safely in modules. Note that the value type MUST be either
159 | * boolean, number, or string.
160 | *
161 | * @param {string} name The distinguished name to provide.
162 | * @param {T} defaultValue
163 | * @return {T} The defined value.
164 | * @template T
165 | */
166 | goog.define = function(name, defaultValue) {
167 | var value = defaultValue;
168 | if (!COMPILED) {
169 | var uncompiledDefines = goog.global.CLOSURE_UNCOMPILED_DEFINES;
170 | var defines = goog.global.CLOSURE_DEFINES;
171 | if (uncompiledDefines &&
172 | // Anti DOM-clobbering runtime check (b/37736576).
173 | /** @type {?} */ (uncompiledDefines).nodeType === undefined &&
174 | Object.prototype.hasOwnProperty.call(uncompiledDefines, name)) {
175 | value = uncompiledDefines[name];
176 | } else if (
177 | defines &&
178 | // Anti DOM-clobbering runtime check (b/37736576).
179 | /** @type {?} */ (defines).nodeType === undefined &&
180 | Object.prototype.hasOwnProperty.call(defines, name)) {
181 | value = defines[name];
182 | }
183 | }
184 | return value;
185 | };
186 |
187 |
188 | /**
189 | * @define {number} Integer year indicating the set of browser features that are
190 | * guaranteed to be present. This is defined to include exactly features that
191 | * work correctly on all "modern" browsers that are stable on January 1 of the
192 | * specified year. For example,
193 | * ```js
194 | * if (goog.FEATURESET_YEAR >= 2019) {
195 | * // use APIs known to be available on all major stable browsers Jan 1, 2019
196 | * } else {
197 | * // polyfill for older browsers
198 | * }
199 | * ```
200 | * This is intended to be the primary define for removing
201 | * unnecessary browser compatibility code (such as ponyfills and workarounds),
202 | * and should inform the default value for most other defines:
203 | * ```js
204 | * const ASSUME_NATIVE_PROMISE =
205 | * goog.define('ASSUME_NATIVE_PROMISE', goog.FEATURESET_YEAR >= 2016);
206 | * ```
207 | *
208 | * The default assumption is that IE9 is the lowest supported browser, which was
209 | * first available Jan 1, 2012.
210 | *
211 | * TODO(user): Reference more thorough documentation when it's available.
212 | */
213 | goog.FEATURESET_YEAR = goog.define('goog.FEATURESET_YEAR', 2012);
214 |
215 |
216 | /**
217 | * @define {boolean} DEBUG is provided as a convenience so that debugging code
218 | * that should not be included in a production. It can be easily stripped
219 | * by specifying --define goog.DEBUG=false to the Closure Compiler aka
220 | * JSCompiler. For example, most toString() methods should be declared inside an
221 | * "if (goog.DEBUG)" conditional because they are generally used for debugging
222 | * purposes and it is difficult for the JSCompiler to statically determine
223 | * whether they are used.
224 | */
225 | goog.DEBUG = goog.define('goog.DEBUG', true);
226 |
227 |
228 | /**
229 | * @define {string} LOCALE defines the locale being used for compilation. It is
230 | * used to select locale specific data to be compiled in js binary. BUILD rule
231 | * can specify this value by "--define goog.LOCALE=" as a compiler
232 | * option.
233 | *
234 | * Take into account that the locale code format is important. You should use
235 | * the canonical Unicode format with hyphen as a delimiter. Language must be
236 | * lowercase, Language Script - Capitalized, Region - UPPERCASE.
237 | * There are few examples: pt-BR, en, en-US, sr-Latin-BO, zh-Hans-CN.
238 | *
239 | * See more info about locale codes here:
240 | * http://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers
241 | *
242 | * For language codes you should use values defined by ISO 693-1. See it here
243 | * http://www.w3.org/WAI/ER/IG/ert/iso639.htm. There is only one exception from
244 | * this rule: the Hebrew language. For legacy reasons the old code (iw) should
245 | * be used instead of the new code (he).
246 | *
247 | */
248 | goog.LOCALE = goog.define('goog.LOCALE', 'en'); // default to en
249 |
250 |
251 | /**
252 | * This method is intended to be used for bookkeeping purposes. We would
253 | * like to distinguish uses of goog.LOCALE used for code stripping purposes
254 | * and uses of goog.LOCALE for other uses (such as URL parameters).
255 | *
256 | * This allows us to ban direct uses of goog.LOCALE and to ensure that all
257 | * code has been transformed to our new localization build scheme.
258 | *
259 | * @return {string}
260 | *
261 | */
262 | goog.getLocale = function() {
263 | return goog.LOCALE;
264 | };
265 |
266 |
267 | /**
268 | * @define {boolean} Whether this code is running on trusted sites.
269 | *
270 | * On untrusted sites, several native functions can be defined or overridden by
271 | * external libraries like Prototype, Datejs, and JQuery and setting this flag
272 | * to false forces closure to use its own implementations when possible.
273 | *
274 | * If your JavaScript can be loaded by a third party site and you are wary about
275 | * relying on non-standard implementations, specify
276 | * "--define goog.TRUSTED_SITE=false" to the compiler.
277 | */
278 | goog.TRUSTED_SITE = goog.define('goog.TRUSTED_SITE', true);
279 |
280 |
281 | /**
282 | * @define {boolean} Whether code that calls {@link goog.setTestOnly} should
283 | * be disallowed in the compilation unit.
284 | */
285 | goog.DISALLOW_TEST_ONLY_CODE =
286 | goog.define('goog.DISALLOW_TEST_ONLY_CODE', COMPILED && !goog.DEBUG);
287 |
288 |
289 | /**
290 | * @define {boolean} Whether to use a Chrome app CSP-compliant method for
291 | * loading scripts via goog.require. @see appendScriptSrcNode_.
292 | */
293 | goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING =
294 | goog.define('goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING', false);
295 |
296 |
297 | /**
298 | * Defines a namespace in Closure.
299 | *
300 | * A namespace may only be defined once in a codebase. It may be defined using
301 | * goog.provide() or goog.module().
302 | *
303 | * The presence of one or more goog.provide() calls in a file indicates
304 | * that the file defines the given objects/namespaces.
305 | * Provided symbols must not be null or undefined.
306 | *
307 | * In addition, goog.provide() creates the object stubs for a namespace
308 | * (for example, goog.provide("goog.foo.bar") will create the object
309 | * goog.foo.bar if it does not already exist).
310 | *
311 | * Build tools also scan for provide/require/module statements
312 | * to discern dependencies, build dependency files (see deps.js), etc.
313 | *
314 | * @see goog.require
315 | * @see goog.module
316 | * @param {string} name Namespace provided by this file in the form
317 | * "goog.package.part".
318 | * deprecated Use goog.module (see b/159289405)
319 | */
320 | goog.provide = function(name) {
321 | if (goog.isInModuleLoader_()) {
322 | throw new Error('goog.provide cannot be used within a module.');
323 | }
324 | if (!COMPILED) {
325 | // Ensure that the same namespace isn't provided twice.
326 | // A goog.module/goog.provide maps a goog.require to a specific file
327 | if (goog.isProvided_(name)) {
328 | throw new Error('Namespace "' + name + '" already declared.');
329 | }
330 | }
331 |
332 | goog.constructNamespace_(name);
333 | };
334 |
335 |
336 | /**
337 | * @param {string} name Namespace provided by this file in the form
338 | * "goog.package.part".
339 | * @param {?Object=} object The object to embed in the namespace.
340 | * @param {boolean=} overwriteImplicit If object is set and a previous call
341 | * implicitly constructed the namespace given by name, this parameter
342 | * controls whether opt_obj should overwrite the implicitly constructed
343 | * namespace or be merged into it. Defaults to false.
344 | * @private
345 | */
346 | goog.constructNamespace_ = function(name, object, overwriteImplicit) {
347 | if (!COMPILED) {
348 | delete goog.implicitNamespaces_[name];
349 |
350 | var namespace = name;
351 | while ((namespace = namespace.substring(0, namespace.lastIndexOf('.')))) {
352 | if (goog.getObjectByName(namespace)) {
353 | break;
354 | }
355 | goog.implicitNamespaces_[namespace] = true;
356 | }
357 | }
358 |
359 | goog.exportPath_(name, object, overwriteImplicit);
360 | };
361 |
362 |
363 | /**
364 | * According to the CSP3 spec a nonce must be a valid base64 string.
365 | * @see https://www.w3.org/TR/CSP3/#grammardef-base64-value
366 | * @private @const
367 | */
368 | goog.NONCE_PATTERN_ = /^[\w+/_-]+[=]{0,2}$/;
369 |
370 |
371 | /**
372 | * Returns CSP nonce, if set for any script tag.
373 | * @param {?Window=} opt_window The window context used to retrieve the nonce.
374 | * Defaults to global context.
375 | * @return {string} CSP nonce or empty string if no nonce is present.
376 | * @private
377 | */
378 | goog.getScriptNonce_ = function(opt_window) {
379 | var doc = (opt_window || goog.global).document;
380 | var script = doc.querySelector && doc.querySelector('script[nonce]');
381 | if (script) {
382 | // Try to get the nonce from the IDL property first, because browsers that
383 | // implement additional nonce protection features (currently only Chrome) to
384 | // prevent nonce stealing via CSS do not expose the nonce via attributes.
385 | // See https://github.com/whatwg/html/issues/2369
386 | var nonce = script['nonce'] || script.getAttribute('nonce');
387 | if (nonce && goog.NONCE_PATTERN_.test(nonce)) {
388 | return nonce;
389 | }
390 | }
391 | return '';
392 | };
393 |
394 |
395 | /**
396 | * Module identifier validation regexp.
397 | * Note: This is a conservative check, it is very possible to be more lenient,
398 | * the primary exclusion here is "/" and "\" and a leading ".", these
399 | * restrictions are intended to leave the door open for using goog.require
400 | * with relative file paths rather than module identifiers.
401 | * @private
402 | */
403 | goog.VALID_MODULE_RE_ = /^[a-zA-Z_$][a-zA-Z0-9._$]*$/;
404 |
405 |
406 | /**
407 | * Defines a module in Closure.
408 | *
409 | * Marks that this file must be loaded as a module and claims the namespace.
410 | *
411 | * A namespace may only be defined once in a codebase. It may be defined using
412 | * goog.provide() or goog.module().
413 | *
414 | * goog.module() has three requirements:
415 | * - goog.module may not be used in the same file as goog.provide.
416 | * - goog.module must be the first statement in the file.
417 | * - only one goog.module is allowed per file.
418 | *
419 | * When a goog.module annotated file is loaded, it is enclosed in
420 | * a strict function closure. This means that:
421 | * - any variables declared in a goog.module file are private to the file
422 | * (not global), though the compiler is expected to inline the module.
423 | * - The code must obey all the rules of "strict" JavaScript.
424 | * - the file will be marked as "use strict"
425 | *
426 | * NOTE: unlike goog.provide, goog.module does not declare any symbols by
427 | * itself. If declared symbols are desired, use
428 | * goog.module.declareLegacyNamespace().
429 | *
430 | *
431 | * See the public goog.module proposal: http://goo.gl/Va1hin
432 | *
433 | * @param {string} name Namespace provided by this file in the form
434 | * "goog.package.part", is expected but not required.
435 | * @return {void}
436 | */
437 | goog.module = function(name) {
438 | if (typeof name !== 'string' || !name ||
439 | name.search(goog.VALID_MODULE_RE_) == -1) {
440 | throw new Error('Invalid module identifier');
441 | }
442 | if (!goog.isInGoogModuleLoader_()) {
443 | throw new Error(
444 | 'Module ' + name + ' has been loaded incorrectly. Note, ' +
445 | 'modules cannot be loaded as normal scripts. They require some kind of ' +
446 | 'pre-processing step. You\'re likely trying to load a module via a ' +
447 | 'script tag or as a part of a concatenated bundle without rewriting the ' +
448 | 'module. For more info see: ' +
449 | 'https://github.com/google/closure-library/wiki/goog.module:-an-ES6-module-like-alternative-to-goog.provide.');
450 | }
451 | if (goog.moduleLoaderState_.moduleName) {
452 | throw new Error('goog.module may only be called once per module.');
453 | }
454 |
455 | // Store the module name for the loader.
456 | goog.moduleLoaderState_.moduleName = name;
457 | if (!COMPILED) {
458 | // Ensure that the same namespace isn't provided twice.
459 | // A goog.module/goog.provide maps a goog.require to a specific file
460 | if (goog.isProvided_(name)) {
461 | throw new Error('Namespace "' + name + '" already declared.');
462 | }
463 | delete goog.implicitNamespaces_[name];
464 | }
465 | };
466 |
467 |
468 | /**
469 | * @param {string} name The module identifier.
470 | * @return {?} The module exports for an already loaded module or null.
471 | *
472 | * Note: This is not an alternative to goog.require, it does not
473 | * indicate a hard dependency, instead it is used to indicate
474 | * an optional dependency or to access the exports of a module
475 | * that has already been loaded.
476 | * @suppress {missingProvide}
477 | */
478 | goog.module.get = function(name) {
479 | return goog.module.getInternal_(name);
480 | };
481 |
482 |
483 | /**
484 | * @param {string} name The module identifier.
485 | * @return {?} The module exports for an already loaded module or null.
486 | * @private
487 | */
488 | goog.module.getInternal_ = function(name) {
489 | if (!COMPILED) {
490 | if (name in goog.loadedModules_) {
491 | return goog.loadedModules_[name].exports;
492 | } else if (!goog.implicitNamespaces_[name]) {
493 | var ns = goog.getObjectByName(name);
494 | return ns != null ? ns : null;
495 | }
496 | }
497 | return null;
498 | };
499 |
500 |
501 | /**
502 | * Types of modules the debug loader can load.
503 | * @enum {string}
504 | */
505 | goog.ModuleType = {
506 | ES6: 'es6',
507 | GOOG: 'goog'
508 | };
509 |
510 |
511 | /**
512 | * @private {?{
513 | * moduleName: (string|undefined),
514 | * declareLegacyNamespace:boolean,
515 | * type: ?goog.ModuleType
516 | * }}
517 | */
518 | goog.moduleLoaderState_ = null;
519 |
520 |
521 | /**
522 | * @private
523 | * @return {boolean} Whether a goog.module or an es6 module is currently being
524 | * initialized.
525 | */
526 | goog.isInModuleLoader_ = function() {
527 | return goog.isInGoogModuleLoader_() || goog.isInEs6ModuleLoader_();
528 | };
529 |
530 |
531 | /**
532 | * @private
533 | * @return {boolean} Whether a goog.module is currently being initialized.
534 | */
535 | goog.isInGoogModuleLoader_ = function() {
536 | return !!goog.moduleLoaderState_ &&
537 | goog.moduleLoaderState_.type == goog.ModuleType.GOOG;
538 | };
539 |
540 |
541 | /**
542 | * @private
543 | * @return {boolean} Whether an es6 module is currently being initialized.
544 | */
545 | goog.isInEs6ModuleLoader_ = function() {
546 | var inLoader = !!goog.moduleLoaderState_ &&
547 | goog.moduleLoaderState_.type == goog.ModuleType.ES6;
548 |
549 | if (inLoader) {
550 | return true;
551 | }
552 |
553 | var jscomp = goog.global['$jscomp'];
554 |
555 | if (jscomp) {
556 | // jscomp may not have getCurrentModulePath if this is a compiled bundle
557 | // that has some of the runtime, but not all of it. This can happen if
558 | // optimizations are turned on so the unused runtime is removed but renaming
559 | // and Closure pass are off (so $jscomp is still named $jscomp and the
560 | // goog.provide/require calls still exist).
561 | if (typeof jscomp.getCurrentModulePath != 'function') {
562 | return false;
563 | }
564 |
565 | // Bundled ES6 module.
566 | return !!jscomp.getCurrentModulePath();
567 | }
568 |
569 | return false;
570 | };
571 |
572 |
573 | /**
574 | * Provide the module's exports as a globally accessible object under the
575 | * module's declared name. This is intended to ease migration to goog.module
576 | * for files that have existing usages.
577 | * @suppress {missingProvide}
578 | */
579 | goog.module.declareLegacyNamespace = function() {
580 | if (!COMPILED && !goog.isInGoogModuleLoader_()) {
581 | throw new Error(
582 | 'goog.module.declareLegacyNamespace must be called from ' +
583 | 'within a goog.module');
584 | }
585 | if (!COMPILED && !goog.moduleLoaderState_.moduleName) {
586 | throw new Error(
587 | 'goog.module must be called prior to ' +
588 | 'goog.module.declareLegacyNamespace.');
589 | }
590 | goog.moduleLoaderState_.declareLegacyNamespace = true;
591 | };
592 |
593 |
594 | /**
595 | * Associates an ES6 module with a Closure module ID so that is available via
596 | * goog.require. The associated ID acts like a goog.module ID - it does not
597 | * create any global names, it is merely available via goog.require /
598 | * goog.module.get / goog.forwardDeclare / goog.requireType. goog.require and
599 | * goog.module.get will return the entire module as if it was import *'d. This
600 | * allows Closure files to reference ES6 modules for the sake of migration.
601 | *
602 | * @param {string} namespace
603 | * @suppress {missingProvide}
604 | */
605 | goog.declareModuleId = function(namespace) {
606 | if (!COMPILED) {
607 | if (!goog.isInEs6ModuleLoader_()) {
608 | throw new Error(
609 | 'goog.declareModuleId may only be called from ' +
610 | 'within an ES6 module');
611 | }
612 | if (goog.moduleLoaderState_ && goog.moduleLoaderState_.moduleName) {
613 | throw new Error(
614 | 'goog.declareModuleId may only be called once per module.');
615 | }
616 | if (namespace in goog.loadedModules_) {
617 | throw new Error(
618 | 'Module with namespace "' + namespace + '" already exists.');
619 | }
620 | }
621 | if (goog.moduleLoaderState_) {
622 | // Not bundled - debug loading.
623 | goog.moduleLoaderState_.moduleName = namespace;
624 | } else {
625 | // Bundled - not debug loading, no module loader state.
626 | var jscomp = goog.global['$jscomp'];
627 | if (!jscomp || typeof jscomp.getCurrentModulePath != 'function') {
628 | throw new Error(
629 | 'Module with namespace "' + namespace +
630 | '" has been loaded incorrectly.');
631 | }
632 | var exports = jscomp.require(jscomp.getCurrentModulePath());
633 | goog.loadedModules_[namespace] = {
634 | exports: exports,
635 | type: goog.ModuleType.ES6,
636 | moduleId: namespace
637 | };
638 | }
639 | };
640 |
641 |
642 | /**
643 | * Marks that the current file should only be used for testing, and never for
644 | * live code in production.
645 | *
646 | * In the case of unit tests, the message may optionally be an exact namespace
647 | * for the test (e.g. 'goog.stringTest'). The linter will then ignore the extra
648 | * provide (if not explicitly defined in the code).
649 | *
650 | * @param {string=} opt_message Optional message to add to the error that's
651 | * raised when used in production code.
652 | */
653 | goog.setTestOnly = function(opt_message) {
654 | if (goog.DISALLOW_TEST_ONLY_CODE) {
655 | opt_message = opt_message || '';
656 | throw new Error(
657 | 'Importing test-only code into non-debug environment' +
658 | (opt_message ? ': ' + opt_message : '.'));
659 | }
660 | };
661 |
662 |
663 | /**
664 | * Forward declares a symbol. This is an indication to the compiler that the
665 | * symbol may be used in the source yet is not required and may not be provided
666 | * in compilation.
667 | *
668 | * The most common usage of forward declaration is code that takes a type as a
669 | * function parameter but does not need to require it. By forward declaring
670 | * instead of requiring, no hard dependency is made, and (if not required
671 | * elsewhere) the namespace may never be required and thus, not be pulled
672 | * into the JavaScript binary. If it is required elsewhere, it will be type
673 | * checked as normal.
674 | *
675 | * Before using goog.forwardDeclare, please read the documentation at
676 | * https://github.com/google/closure-compiler/wiki/Bad-Type-Annotation to
677 | * understand the options and tradeoffs when working with forward declarations.
678 | *
679 | * @param {string} name The namespace to forward declare in the form of
680 | * "goog.package.part".
681 | * @deprecated See go/noforwarddeclaration, Use `goog.requireType` instead.
682 | */
683 | goog.forwardDeclare = function(name) {};
684 |
685 |
686 | /**
687 | * Forward declare type information. Used to assign types to goog.global
688 | * referenced object that would otherwise result in unknown type references
689 | * and thus block property disambiguation.
690 | */
691 | goog.forwardDeclare('Document');
692 | goog.forwardDeclare('HTMLScriptElement');
693 | goog.forwardDeclare('XMLHttpRequest');
694 |
695 |
696 | if (!COMPILED) {
697 | /**
698 | * Check if the given name has been goog.provided. This will return false for
699 | * names that are available only as implicit namespaces.
700 | * @param {string} name name of the object to look for.
701 | * @return {boolean} Whether the name has been provided.
702 | * @private
703 | */
704 | goog.isProvided_ = function(name) {
705 | return (name in goog.loadedModules_) ||
706 | (!goog.implicitNamespaces_[name] && goog.getObjectByName(name) != null);
707 | };
708 |
709 | /**
710 | * Namespaces implicitly defined by goog.provide. For example,
711 | * goog.provide('goog.events.Event') implicitly declares that 'goog' and
712 | * 'goog.events' must be namespaces.
713 | *
714 | * @type {!Object}
715 | * @private
716 | */
717 | goog.implicitNamespaces_ = {'goog.module': true};
718 |
719 | // NOTE: We add goog.module as an implicit namespace as goog.module is defined
720 | // here and because the existing module package has not been moved yet out of
721 | // the goog.module namespace. This satisifies both the debug loader and
722 | // ahead-of-time dependency management.
723 | }
724 |
725 |
726 | /**
727 | * Returns an object based on its fully qualified external name. The object
728 | * is not found if null or undefined. If you are using a compilation pass that
729 | * renames property names beware that using this function will not find renamed
730 | * properties.
731 | *
732 | * @param {string} name The fully qualified name.
733 | * @param {Object=} opt_obj The object within which to look; default is
734 | * |goog.global|.
735 | * @return {?} The value (object or primitive) or, if not found, null.
736 | */
737 | goog.getObjectByName = function(name, opt_obj) {
738 | var parts = name.split('.');
739 | var cur = opt_obj || goog.global;
740 | for (var i = 0; i < parts.length; i++) {
741 | cur = cur[parts[i]];
742 | if (cur == null) {
743 | return null;
744 | }
745 | }
746 | return cur;
747 | };
748 |
749 |
750 | /**
751 | * Adds a dependency from a file to the files it requires.
752 | * @param {string} relPath The path to the js file.
753 | * @param {!Array} provides An array of strings with
754 | * the names of the objects this file provides.
755 | * @param {!Array} requires An array of strings with
756 | * the names of the objects this file requires.
757 | * @param {boolean|!Object=} opt_loadFlags Parameters indicating
758 | * how the file must be loaded. The boolean 'true' is equivalent
759 | * to {'module': 'goog'} for backwards-compatibility. Valid properties
760 | * and values include {'module': 'goog'} and {'lang': 'es6'}.
761 | */
762 | goog.addDependency = function(relPath, provides, requires, opt_loadFlags) {
763 | if (!COMPILED && goog.DEPENDENCIES_ENABLED) {
764 | goog.debugLoader_.addDependency(relPath, provides, requires, opt_loadFlags);
765 | }
766 | };
767 |
768 |
769 | // NOTE(nnaze): The debug DOM loader was included in base.js as an original way
770 | // to do "debug-mode" development. The dependency system can sometimes be
771 | // confusing, as can the debug DOM loader's asynchronous nature.
772 | //
773 | // With the DOM loader, a call to goog.require() is not blocking -- the script
774 | // will not load until some point after the current script. If a namespace is
775 | // needed at runtime, it needs to be defined in a previous script, or loaded via
776 | // require() with its registered dependencies.
777 | //
778 | // User-defined namespaces may need their own deps file. For a reference on
779 | // creating a deps file, see:
780 | // Externally: https://developers.google.com/closure/library/docs/depswriter
781 | //
782 | // Because of legacy clients, the DOM loader can't be easily removed from
783 | // base.js. Work was done to make it disableable or replaceable for
784 | // different environments (DOM-less JavaScript interpreters like Rhino or V8,
785 | // for example). See bootstrap/ for more information.
786 |
787 |
788 | /**
789 | * @define {boolean} Whether to enable the debug loader.
790 | *
791 | * If enabled, a call to goog.require() will attempt to load the namespace by
792 | * appending a script tag to the DOM (if the namespace has been registered).
793 | *
794 | * If disabled, goog.require() will simply assert that the namespace has been
795 | * provided (and depend on the fact that some outside tool correctly ordered
796 | * the script).
797 | */
798 | goog.ENABLE_DEBUG_LOADER = goog.define('goog.ENABLE_DEBUG_LOADER', true);
799 |
800 |
801 | /**
802 | * @param {string} msg
803 | * @private
804 | */
805 | goog.logToConsole_ = function(msg) {
806 | if (goog.global.console) {
807 | goog.global.console['error'](msg);
808 | }
809 | };
810 |
811 |
812 | /**
813 | * Implements a system for the dynamic resolution of dependencies that works in
814 | * parallel with the BUILD system.
815 | *
816 | * Note that all calls to goog.require will be stripped by the compiler.
817 | *
818 | * @see goog.provide
819 | * @param {string} namespace Namespace (as was given in goog.provide,
820 | * goog.module, or goog.declareModuleId) in the form
821 | * "goog.package.part".
822 | * @return {?} If called within a goog.module or ES6 module file, the associated
823 | * namespace or module otherwise null.
824 | */
825 | goog.require = function(namespace) {
826 | if (!COMPILED) {
827 | // Might need to lazy load on old IE.
828 | if (goog.ENABLE_DEBUG_LOADER) {
829 | goog.debugLoader_.requested(namespace);
830 | }
831 |
832 | // If the object already exists we do not need to do anything.
833 | if (goog.isProvided_(namespace)) {
834 | if (goog.isInModuleLoader_()) {
835 | return goog.module.getInternal_(namespace);
836 | }
837 | } else if (goog.ENABLE_DEBUG_LOADER) {
838 | var moduleLoaderState = goog.moduleLoaderState_;
839 | goog.moduleLoaderState_ = null;
840 | try {
841 | goog.debugLoader_.load_(namespace);
842 | } finally {
843 | goog.moduleLoaderState_ = moduleLoaderState;
844 | }
845 | }
846 |
847 | return null;
848 | }
849 | };
850 |
851 |
852 | /**
853 | * Requires a symbol for its type information. This is an indication to the
854 | * compiler that the symbol may appear in type annotations, yet it is not
855 | * referenced at runtime.
856 | *
857 | * When called within a goog.module or ES6 module file, the return value may be
858 | * assigned to or destructured into a variable, but it may not be otherwise used
859 | * in code outside of a type annotation.
860 | *
861 | * Note that all calls to goog.requireType will be stripped by the compiler.
862 | *
863 | * @param {string} namespace Namespace (as was given in goog.provide,
864 | * goog.module, or goog.declareModuleId) in the form
865 | * "goog.package.part".
866 | * @return {?}
867 | */
868 | goog.requireType = function(namespace) {
869 | // Return an empty object so that single-level destructuring of the return
870 | // value doesn't crash at runtime when using the debug loader. Multi-level
871 | // destructuring isn't supported.
872 | return {};
873 | };
874 |
875 |
876 | /**
877 | * Path for included scripts.
878 | * @type {string}
879 | */
880 | goog.basePath = '';
881 |
882 |
883 | /**
884 | * A hook for overriding the base path.
885 | * @type {string|undefined}
886 | */
887 | goog.global.CLOSURE_BASE_PATH;
888 |
889 |
890 | /**
891 | * Whether to attempt to load Closure's deps file. By default, when uncompiled,
892 | * deps files will attempt to be loaded.
893 | * @type {boolean|undefined}
894 | */
895 | goog.global.CLOSURE_NO_DEPS;
896 |
897 |
898 | /**
899 | * A function to import a single script. This is meant to be overridden when
900 | * Closure is being run in non-HTML contexts, such as web workers. It's defined
901 | * in the global scope so that it can be set before base.js is loaded, which
902 | * allows deps.js to be imported properly.
903 | *
904 | * The first parameter the script source, which is a relative URI. The second,
905 | * optional parameter is the script contents, in the event the script needed
906 | * transformation. It should return true if the script was imported, false
907 | * otherwise.
908 | * @type {(function(string, string=): boolean)|undefined}
909 | */
910 | goog.global.CLOSURE_IMPORT_SCRIPT;
911 |
912 |
913 | /**
914 | * Null function used for default values of callbacks, etc.
915 | * @return {void} Nothing.
916 | * @deprecated use '()=>{}' or 'function(){}' instead.
917 | */
918 | goog.nullFunction = function() {};
919 |
920 |
921 | /**
922 | * When defining a class Foo with an abstract method bar(), you can do:
923 | * Foo.prototype.bar = goog.abstractMethod
924 | *
925 | * Now if a subclass of Foo fails to override bar(), an error will be thrown
926 | * when bar() is invoked.
927 | *
928 | * @type {!Function}
929 | * @throws {Error} when invoked to indicate the method should be overridden.
930 | * @deprecated Use "@abstract" annotation instead of goog.abstractMethod in new
931 | * code. See
932 | * https://github.com/google/closure-compiler/wiki/@abstract-classes-and-methods
933 | */
934 | goog.abstractMethod = function() {
935 | throw new Error('unimplemented abstract method');
936 | };
937 |
938 |
939 | /**
940 | * Adds a `getInstance` static method that always returns the same
941 | * instance object.
942 | * @param {!Function} ctor The constructor for the class to add the static
943 | * method to.
944 | * @suppress {missingProperties} 'instance_' isn't a property on 'Function'
945 | * but we don't have a better type to use here.
946 | */
947 | goog.addSingletonGetter = function(ctor) {
948 | // instance_ is immediately set to prevent issues with sealed constructors
949 | // such as are encountered when a constructor is returned as the export object
950 | // of a goog.module in unoptimized code.
951 | // Delcare type to avoid conformance violations that ctor.instance_ is unknown
952 | /** @type {undefined|!Object} @suppress {underscore} */
953 | ctor.instance_ = undefined;
954 | ctor.getInstance = function() {
955 | if (ctor.instance_) {
956 | return ctor.instance_;
957 | }
958 | if (goog.DEBUG) {
959 | // NOTE: JSCompiler can't optimize away Array#push.
960 | goog.instantiatedSingletons_[goog.instantiatedSingletons_.length] = ctor;
961 | }
962 | // Cast to avoid conformance violations that ctor.instance_ is unknown
963 | return /** @type {!Object|undefined} */ (ctor.instance_) = new ctor;
964 | };
965 | };
966 |
967 |
968 | /**
969 | * All singleton classes that have been instantiated, for testing. Don't read
970 | * it directly, use the `goog.testing.singleton` module. The compiler
971 | * removes this variable if unused.
972 | * @type {!Array}
973 | * @private
974 | */
975 | goog.instantiatedSingletons_ = [];
976 |
977 |
978 | /**
979 | * @define {boolean} Whether to load goog.modules using `eval` when using
980 | * the debug loader. This provides a better debugging experience as the
981 | * source is unmodified and can be edited using Chrome Workspaces or similar.
982 | * However in some environments the use of `eval` is banned
983 | * so we provide an alternative.
984 | */
985 | goog.LOAD_MODULE_USING_EVAL = goog.define('goog.LOAD_MODULE_USING_EVAL', true);
986 |
987 |
988 | /**
989 | * @define {boolean} Whether the exports of goog.modules should be sealed when
990 | * possible.
991 | */
992 | goog.SEAL_MODULE_EXPORTS = goog.define('goog.SEAL_MODULE_EXPORTS', goog.DEBUG);
993 |
994 |
995 | /**
996 | * The registry of initialized modules:
997 | * The module identifier or path to module exports map.
998 | * @private @const {!Object}
999 | */
1000 | goog.loadedModules_ = {};
1001 |
1002 |
1003 | /**
1004 | * True if the debug loader enabled and used.
1005 | * @const {boolean}
1006 | */
1007 | goog.DEPENDENCIES_ENABLED = !COMPILED && goog.ENABLE_DEBUG_LOADER;
1008 |
1009 |
1010 | /**
1011 | * @define {string} How to decide whether to transpile. Valid values
1012 | * are 'always', 'never', and 'detect'. The default ('detect') is to
1013 | * use feature detection to determine which language levels need
1014 | * transpilation.
1015 | */
1016 | // NOTE(sdh): we could expand this to accept a language level to bypass
1017 | // detection: e.g. goog.TRANSPILE == 'es5' would transpile ES6 files but
1018 | // would leave ES3 and ES5 files alone.
1019 | goog.TRANSPILE = goog.define('goog.TRANSPILE', 'detect');
1020 |
1021 | /**
1022 | * @define {boolean} If true assume that ES modules have already been
1023 | * transpiled by the jscompiler (in the same way that transpile.js would
1024 | * transpile them - to jscomp modules). Useful only for servers that wish to use
1025 | * the debug loader and transpile server side. Thus this is only respected if
1026 | * goog.TRANSPILE is "never".
1027 | */
1028 | goog.ASSUME_ES_MODULES_TRANSPILED =
1029 | goog.define('goog.ASSUME_ES_MODULES_TRANSPILED', false);
1030 |
1031 |
1032 | /**
1033 | * @define {string} If a file needs to be transpiled what the output language
1034 | * should be. By default this is the highest language level this file detects
1035 | * the current environment supports. Generally this flag should not be set, but
1036 | * it could be useful to override. Example: If the current environment supports
1037 | * ES6 then by default ES7+ files will be transpiled to ES6, unless this is
1038 | * overridden.
1039 | *
1040 | * Valid values include: es3, es5, es6, es7, and es8. Anything not recognized
1041 | * is treated as es3.
1042 | *
1043 | * Note that setting this value does not force transpilation. Just if
1044 | * transpilation occurs this will be the output. So this is most useful when
1045 | * goog.TRANSPILE is set to 'always' and then forcing the language level to be
1046 | * something lower than what the environment detects.
1047 | */
1048 | goog.TRANSPILE_TO_LANGUAGE = goog.define('goog.TRANSPILE_TO_LANGUAGE', '');
1049 |
1050 |
1051 | /**
1052 | * @define {string} Path to the transpiler. Executing the script at this
1053 | * path (relative to base.js) should define a function $jscomp.transpile.
1054 | */
1055 | goog.TRANSPILER = goog.define('goog.TRANSPILER', 'transpile.js');
1056 |
1057 |
1058 | /**
1059 | * @define {string} Trusted Types policy name. If non-empty then Closure will
1060 | * use Trusted Types.
1061 | */
1062 | goog.TRUSTED_TYPES_POLICY_NAME =
1063 | goog.define('goog.TRUSTED_TYPES_POLICY_NAME', 'goog');
1064 |
1065 |
1066 | /**
1067 | * @package {?boolean}
1068 | * Visible for testing.
1069 | */
1070 | goog.hasBadLetScoping = null;
1071 |
1072 |
1073 | /**
1074 | * @param {function(?):?|string} moduleDef The module definition.
1075 | */
1076 | goog.loadModule = function(moduleDef) {
1077 | // NOTE: we allow function definitions to be either in the from
1078 | // of a string to eval (which keeps the original source intact) or
1079 | // in a eval forbidden environment (CSP) we allow a function definition
1080 | // which in its body must call `goog.module`, and return the exports
1081 | // of the module.
1082 | var previousState = goog.moduleLoaderState_;
1083 | try {
1084 | goog.moduleLoaderState_ = {
1085 | moduleName: '',
1086 | declareLegacyNamespace: false,
1087 | type: goog.ModuleType.GOOG
1088 | };
1089 | var origExports = {};
1090 | var exports = origExports;
1091 | if (typeof moduleDef === 'function') {
1092 | exports = moduleDef.call(undefined, exports);
1093 | } else if (typeof moduleDef === 'string') {
1094 | exports = goog.loadModuleFromSource_.call(undefined, exports, moduleDef);
1095 | } else {
1096 | throw new Error('Invalid module definition');
1097 | }
1098 |
1099 | var moduleName = goog.moduleLoaderState_.moduleName;
1100 | if (typeof moduleName === 'string' && moduleName) {
1101 | // Don't seal legacy namespaces as they may be used as a parent of
1102 | // another namespace
1103 | if (goog.moduleLoaderState_.declareLegacyNamespace) {
1104 | // Whether exports was overwritten via default export assignment.
1105 | // This is important for legacy namespaces as it dictates whether
1106 | // previously a previously loaded implicit namespace should be clobbered
1107 | // or not.
1108 | var isDefaultExport = origExports !== exports;
1109 | goog.constructNamespace_(moduleName, exports, isDefaultExport);
1110 | } else if (
1111 | goog.SEAL_MODULE_EXPORTS && Object.seal &&
1112 | typeof exports == 'object' && exports != null) {
1113 | Object.seal(exports);
1114 | }
1115 |
1116 | var data = {
1117 | exports: exports,
1118 | type: goog.ModuleType.GOOG,
1119 | moduleId: goog.moduleLoaderState_.moduleName
1120 | };
1121 | goog.loadedModules_[moduleName] = data;
1122 | } else {
1123 | throw new Error('Invalid module name \"' + moduleName + '\"');
1124 | }
1125 | } finally {
1126 | goog.moduleLoaderState_ = previousState;
1127 | }
1128 | };
1129 |
1130 |
1131 | /**
1132 | * @private @const
1133 | */
1134 | goog.loadModuleFromSource_ =
1135 | /** @type {function(!Object, string):?} */ (function(exports) {
1136 | // NOTE: we avoid declaring parameters or local variables here to avoid
1137 | // masking globals or leaking values into the module definition.
1138 | 'use strict';
1139 | eval(goog.CLOSURE_EVAL_PREFILTER_.createScript(arguments[1]));
1140 | return exports;
1141 | });
1142 |
1143 |
1144 | /**
1145 | * Normalize a file path by removing redundant ".." and extraneous "." file
1146 | * path components.
1147 | * @param {string} path
1148 | * @return {string}
1149 | * @private
1150 | */
1151 | goog.normalizePath_ = function(path) {
1152 | var components = path.split('/');
1153 | var i = 0;
1154 | while (i < components.length) {
1155 | if (components[i] == '.') {
1156 | components.splice(i, 1);
1157 | } else if (
1158 | i && components[i] == '..' && components[i - 1] &&
1159 | components[i - 1] != '..') {
1160 | components.splice(--i, 2);
1161 | } else {
1162 | i++;
1163 | }
1164 | }
1165 | return components.join('/');
1166 | };
1167 |
1168 |
1169 | /**
1170 | * Provides a hook for loading a file when using Closure's goog.require() API
1171 | * with goog.modules. In particular this hook is provided to support Node.js.
1172 | *
1173 | * @type {(function(string):string)|undefined}
1174 | */
1175 | goog.global.CLOSURE_LOAD_FILE_SYNC;
1176 |
1177 |
1178 | /**
1179 | * Loads file by synchronous XHR. Should not be used in production environments.
1180 | * @param {string} src Source URL.
1181 | * @return {?string} File contents, or null if load failed.
1182 | * @private
1183 | */
1184 | goog.loadFileSync_ = function(src) {
1185 | if (goog.global.CLOSURE_LOAD_FILE_SYNC) {
1186 | return goog.global.CLOSURE_LOAD_FILE_SYNC(src);
1187 | } else {
1188 | try {
1189 | /** @type {XMLHttpRequest} */
1190 | var xhr = new goog.global['XMLHttpRequest']();
1191 | xhr.open('get', src, false);
1192 | xhr.send();
1193 | // NOTE: Successful http: requests have a status of 200, but successful
1194 | // file: requests may have a status of zero. Any other status, or a
1195 | // thrown exception (particularly in case of file: requests) indicates
1196 | // some sort of error, which we treat as a missing or unavailable file.
1197 | return xhr.status == 0 || xhr.status == 200 ? xhr.responseText : null;
1198 | } catch (err) {
1199 | // No need to rethrow or log, since errors should show up on their own.
1200 | return null;
1201 | }
1202 | }
1203 | };
1204 |
1205 |
1206 | /**
1207 | * Lazily retrieves the transpiler and applies it to the source.
1208 | * @param {string} code JS code.
1209 | * @param {string} path Path to the code.
1210 | * @param {string} target Language level output.
1211 | * @return {string} The transpiled code.
1212 | * @private
1213 | */
1214 | goog.transpile_ = function(code, path, target) {
1215 | var jscomp = goog.global['$jscomp'];
1216 | if (!jscomp) {
1217 | goog.global['$jscomp'] = jscomp = {};
1218 | }
1219 | var transpile = jscomp.transpile;
1220 | if (!transpile) {
1221 | var transpilerPath = goog.basePath + goog.TRANSPILER;
1222 | var transpilerCode = goog.loadFileSync_(transpilerPath);
1223 | if (transpilerCode) {
1224 | // This must be executed synchronously, since by the time we know we
1225 | // need it, we're about to load and write the ES6 code synchronously,
1226 | // so a normal script-tag load will be too slow. Wrapped in a function
1227 | // so that code is eval'd in the global scope.
1228 | (function() {
1229 | (0, eval)(transpilerCode + '\n//# sourceURL=' + transpilerPath);
1230 | }).call(goog.global);
1231 | // Even though the transpiler is optional, if $gwtExport is found, it's
1232 | // a sign the transpiler was loaded and the $jscomp.transpile *should*
1233 | // be there.
1234 | if (goog.global['$gwtExport'] && goog.global['$gwtExport']['$jscomp'] &&
1235 | !goog.global['$gwtExport']['$jscomp']['transpile']) {
1236 | throw new Error(
1237 | 'The transpiler did not properly export the "transpile" ' +
1238 | 'method. $gwtExport: ' + JSON.stringify(goog.global['$gwtExport']));
1239 | }
1240 | // transpile.js only exports a single $jscomp function, transpile. We
1241 | // grab just that and add it to the existing definition of $jscomp which
1242 | // contains the polyfills.
1243 | goog.global['$jscomp'].transpile =
1244 | goog.global['$gwtExport']['$jscomp']['transpile'];
1245 | jscomp = goog.global['$jscomp'];
1246 | transpile = jscomp.transpile;
1247 | }
1248 | }
1249 | if (!transpile) {
1250 | // The transpiler is an optional component. If it's not available then
1251 | // replace it with a pass-through function that simply logs.
1252 | var suffix = ' requires transpilation but no transpiler was found.';
1253 | transpile = jscomp.transpile = function(code, path) {
1254 | // TODO(sdh): figure out some way to get this error to show up
1255 | // in test results, noting that the failure may occur in many
1256 | // different ways, including in loadModule() before the test
1257 | // runner even comes up.
1258 | goog.logToConsole_(path + suffix);
1259 | return code;
1260 | };
1261 | }
1262 | // Note: any transpilation errors/warnings will be logged to the console.
1263 | return transpile(code, path, target);
1264 | };
1265 |
1266 | //==============================================================================
1267 | // Language Enhancements
1268 | //==============================================================================
1269 |
1270 |
1271 | /**
1272 | * This is a "fixed" version of the typeof operator. It differs from the typeof
1273 | * operator in such a way that null returns 'null' and arrays return 'array'.
1274 | * @param {?} value The value to get the type of.
1275 | * @return {string} The name of the type.
1276 | */
1277 | goog.typeOf = function(value) {
1278 | var s = typeof value;
1279 |
1280 | if (s != 'object') {
1281 | return s;
1282 | }
1283 |
1284 | if (!value) {
1285 | return 'null';
1286 | }
1287 |
1288 | if (Array.isArray(value)) {
1289 | return 'array';
1290 | }
1291 | return s;
1292 | };
1293 |
1294 |
1295 | /**
1296 | * Returns true if the object looks like an array. To qualify as array like
1297 | * the value needs to be either a NodeList or an object with a Number length
1298 | * property. Note that for this function neither strings nor functions are
1299 | * considered "array-like".
1300 | *
1301 | * @param {?} val Variable to test.
1302 | * @return {boolean} Whether variable is an array.
1303 | */
1304 | goog.isArrayLike = function(val) {
1305 | var type = goog.typeOf(val);
1306 | // We do not use goog.isObject here in order to exclude function values.
1307 | return type == 'array' || type == 'object' && typeof val.length == 'number';
1308 | };
1309 |
1310 |
1311 | /**
1312 | * Returns true if the object looks like a Date. To qualify as Date-like the
1313 | * value needs to be an object and have a getFullYear() function.
1314 | * @param {?} val Variable to test.
1315 | * @return {boolean} Whether variable is a like a Date.
1316 | */
1317 | goog.isDateLike = function(val) {
1318 | return goog.isObject(val) && typeof val.getFullYear == 'function';
1319 | };
1320 |
1321 |
1322 | /**
1323 | * Returns true if the specified value is an object. This includes arrays and
1324 | * functions.
1325 | * @param {?} val Variable to test.
1326 | * @return {boolean} Whether variable is an object.
1327 | */
1328 | goog.isObject = function(val) {
1329 | var type = typeof val;
1330 | return type == 'object' && val != null || type == 'function';
1331 | // return Object(val) === val also works, but is slower, especially if val is
1332 | // not an object.
1333 | };
1334 |
1335 |
1336 | /**
1337 | * Gets a unique ID for an object. This mutates the object so that further calls
1338 | * with the same object as a parameter returns the same value. The unique ID is
1339 | * guaranteed to be unique across the current session amongst objects that are
1340 | * passed into `getUid`. There is no guarantee that the ID is unique or
1341 | * consistent across sessions. It is unsafe to generate unique ID for function
1342 | * prototypes.
1343 | *
1344 | * @param {Object} obj The object to get the unique ID for.
1345 | * @return {number} The unique ID for the object.
1346 | */
1347 | goog.getUid = function(obj) {
1348 | // TODO(arv): Make the type stricter, do not accept null.
1349 | return Object.prototype.hasOwnProperty.call(obj, goog.UID_PROPERTY_) &&
1350 | obj[goog.UID_PROPERTY_] ||
1351 | (obj[goog.UID_PROPERTY_] = ++goog.uidCounter_);
1352 | };
1353 |
1354 |
1355 | /**
1356 | * Whether the given object is already assigned a unique ID.
1357 | *
1358 | * This does not modify the object.
1359 | *
1360 | * @param {!Object} obj The object to check.
1361 | * @return {boolean} Whether there is an assigned unique id for the object.
1362 | */
1363 | goog.hasUid = function(obj) {
1364 | return !!obj[goog.UID_PROPERTY_];
1365 | };
1366 |
1367 |
1368 | /**
1369 | * Removes the unique ID from an object. This is useful if the object was
1370 | * previously mutated using `goog.getUid` in which case the mutation is
1371 | * undone.
1372 | * @param {Object} obj The object to remove the unique ID field from.
1373 | */
1374 | goog.removeUid = function(obj) {
1375 | // TODO(arv): Make the type stricter, do not accept null.
1376 |
1377 | // In IE, DOM nodes are not instances of Object and throw an exception if we
1378 | // try to delete. Instead we try to use removeAttribute.
1379 | if (obj !== null && 'removeAttribute' in obj) {
1380 | obj.removeAttribute(goog.UID_PROPERTY_);
1381 | }
1382 |
1383 | try {
1384 | delete obj[goog.UID_PROPERTY_];
1385 | } catch (ex) {
1386 | }
1387 | };
1388 |
1389 |
1390 | /**
1391 | * Name for unique ID property. Initialized in a way to help avoid collisions
1392 | * with other closure JavaScript on the same page.
1393 | * @type {string}
1394 | * @private
1395 | */
1396 | goog.UID_PROPERTY_ = 'closure_uid_' + ((Math.random() * 1e9) >>> 0);
1397 |
1398 |
1399 | /**
1400 | * Counter for UID.
1401 | * @type {number}
1402 | * @private
1403 | */
1404 | goog.uidCounter_ = 0;
1405 |
1406 |
1407 | /**
1408 | * Clones a value. The input may be an Object, Array, or basic type. Objects and
1409 | * arrays will be cloned recursively.
1410 | *
1411 | * WARNINGS:
1412 | * goog.cloneObject
does not detect reference loops. Objects that
1413 | * refer to themselves will cause infinite recursion.
1414 | *
1415 | * goog.cloneObject
is unaware of unique identifiers, and copies
1416 | * UIDs created by getUid
into cloned results.
1417 | *
1418 | * @param {*} obj The value to clone.
1419 | * @return {*} A clone of the input value.
1420 | * @deprecated goog.cloneObject is unsafe. Prefer the goog.object methods.
1421 | */
1422 | goog.cloneObject = function(obj) {
1423 | var type = goog.typeOf(obj);
1424 | if (type == 'object' || type == 'array') {
1425 | if (typeof obj.clone === 'function') {
1426 | return obj.clone();
1427 | }
1428 | if (typeof Map !== 'undefined' && obj instanceof Map) {
1429 | return new Map(obj);
1430 | } else if (typeof Set !== 'undefined' && obj instanceof Set) {
1431 | return new Set(obj);
1432 | }
1433 | var clone = type == 'array' ? [] : {};
1434 | for (var key in obj) {
1435 | clone[key] = goog.cloneObject(obj[key]);
1436 | }
1437 | return clone;
1438 | }
1439 |
1440 | return obj;
1441 | };
1442 |
1443 |
1444 | /**
1445 | * A native implementation of goog.bind.
1446 | * @param {?function(this:T, ...)} fn A function to partially apply.
1447 | * @param {T} selfObj Specifies the object which this should point to when the
1448 | * function is run.
1449 | * @param {...*} var_args Additional arguments that are partially applied to the
1450 | * function.
1451 | * @return {!Function} A partially-applied form of the function goog.bind() was
1452 | * invoked as a method of.
1453 | * @template T
1454 | * @private
1455 | */
1456 | goog.bindNative_ = function(fn, selfObj, var_args) {
1457 | return /** @type {!Function} */ (fn.call.apply(fn.bind, arguments));
1458 | };
1459 |
1460 |
1461 | /**
1462 | * A pure-JS implementation of goog.bind.
1463 | * @param {?function(this:T, ...)} fn A function to partially apply.
1464 | * @param {T} selfObj Specifies the object which this should point to when the
1465 | * function is run.
1466 | * @param {...*} var_args Additional arguments that are partially applied to the
1467 | * function.
1468 | * @return {!Function} A partially-applied form of the function goog.bind() was
1469 | * invoked as a method of.
1470 | * @template T
1471 | * @private
1472 | */
1473 | goog.bindJs_ = function(fn, selfObj, var_args) {
1474 | if (!fn) {
1475 | throw new Error();
1476 | }
1477 |
1478 | if (arguments.length > 2) {
1479 | var boundArgs = Array.prototype.slice.call(arguments, 2);
1480 | return function() {
1481 | // Prepend the bound arguments to the current arguments.
1482 | var newArgs = Array.prototype.slice.call(arguments);
1483 | Array.prototype.unshift.apply(newArgs, boundArgs);
1484 | return fn.apply(selfObj, newArgs);
1485 | };
1486 |
1487 | } else {
1488 | return function() {
1489 | return fn.apply(selfObj, arguments);
1490 | };
1491 | }
1492 | };
1493 |
1494 |
1495 | /**
1496 | * Partially applies this function to a particular 'this object' and zero or
1497 | * more arguments. The result is a new function with some arguments of the first
1498 | * function pre-filled and the value of this 'pre-specified'.
1499 | *
1500 | * Remaining arguments specified at call-time are appended to the pre-specified
1501 | * ones.
1502 | *
1503 | * Also see: {@link #partial}.
1504 | *
1505 | * Usage:
1506 | * var barMethBound = goog.bind(myFunction, myObj, 'arg1', 'arg2');
1507 | * barMethBound('arg3', 'arg4');
1508 | *
1509 | * @param {?function(this:T, ...)} fn A function to partially apply.
1510 | * @param {T} selfObj Specifies the object which this should point to when the
1511 | * function is run.
1512 | * @param {...*} var_args Additional arguments that are partially applied to the
1513 | * function.
1514 | * @return {!Function} A partially-applied form of the function goog.bind() was
1515 | * invoked as a method of.
1516 | * @template T
1517 | * @suppress {deprecated} See above.
1518 | * @deprecated use `=> {}` or Function.prototype.bind instead.
1519 | */
1520 | goog.bind = function(fn, selfObj, var_args) {
1521 | // TODO(nicksantos): narrow the type signature.
1522 | if (Function.prototype.bind &&
1523 | // NOTE(nicksantos): Somebody pulled base.js into the default Chrome
1524 | // extension environment. This means that for Chrome extensions, they get
1525 | // the implementation of Function.prototype.bind that calls goog.bind
1526 | // instead of the native one. Even worse, we don't want to introduce a
1527 | // circular dependency between goog.bind and Function.prototype.bind, so
1528 | // we have to hack this to make sure it works correctly.
1529 | Function.prototype.bind.toString().indexOf('native code') != -1) {
1530 | goog.bind = goog.bindNative_;
1531 | } else {
1532 | goog.bind = goog.bindJs_;
1533 | }
1534 | return goog.bind.apply(null, arguments);
1535 | };
1536 |
1537 |
1538 | /**
1539 | * Like goog.bind(), except that a 'this object' is not required. Useful when
1540 | * the target function is already bound.
1541 | *
1542 | * Usage:
1543 | * var g = goog.partial(f, arg1, arg2);
1544 | * g(arg3, arg4);
1545 | *
1546 | * @param {Function} fn A function to partially apply.
1547 | * @param {...*} var_args Additional arguments that are partially applied to fn.
1548 | * @return {!Function} A partially-applied form of the function goog.partial()
1549 | * was invoked as a method of.
1550 | */
1551 | goog.partial = function(fn, var_args) {
1552 | var args = Array.prototype.slice.call(arguments, 1);
1553 | return function() {
1554 | // Clone the array (with slice()) and append additional arguments
1555 | // to the existing arguments.
1556 | var newArgs = args.slice();
1557 | newArgs.push.apply(newArgs, arguments);
1558 | return fn.apply(/** @type {?} */ (this), newArgs);
1559 | };
1560 | };
1561 |
1562 |
1563 | /**
1564 | * Copies all the members of a source object to a target object. This method
1565 | * does not work on all browsers for all objects that contain keys such as
1566 | * toString or hasOwnProperty. Use goog.object.extend for this purpose.
1567 | *
1568 | * NOTE: Some have advocated for the use of goog.mixin to setup classes
1569 | * with multiple inheritence (traits, mixins, etc). However, as it simply
1570 | * uses "for in", this is not compatible with ES6 classes whose methods are
1571 | * non-enumerable. Changing this, would break cases where non-enumerable
1572 | * properties are not expected.
1573 | *
1574 | * @param {Object} target Target.
1575 | * @param {Object} source Source.
1576 | * @deprecated Prefer Object.assign
1577 | */
1578 | goog.mixin = function(target, source) {
1579 | for (var x in source) {
1580 | target[x] = source[x];
1581 | }
1582 |
1583 | // For IE7 or lower, the for-in-loop does not contain any properties that are
1584 | // not enumerable on the prototype object (for example, isPrototypeOf from
1585 | // Object.prototype) but also it will not include 'replace' on objects that
1586 | // extend String and change 'replace' (not that it is common for anyone to
1587 | // extend anything except Object).
1588 | };
1589 |
1590 |
1591 | /**
1592 | * @return {number} An integer value representing the number of milliseconds
1593 | * between midnight, January 1, 1970 and the current time.
1594 | * @deprecated Use Date.now
1595 | */
1596 | goog.now = function() {
1597 | return Date.now();
1598 | };
1599 |
1600 |
1601 | /**
1602 | * Evals JavaScript in the global scope.
1603 | *
1604 | * Throws an exception if neither execScript or eval is defined.
1605 | * @param {string|!TrustedScript} script JavaScript string.
1606 | */
1607 | goog.globalEval = function(script) {
1608 | (0, eval)(script);
1609 | };
1610 |
1611 |
1612 | /**
1613 | * Optional map of CSS class names to obfuscated names used with
1614 | * goog.getCssName().
1615 | * @private {!Object|undefined}
1616 | * @see goog.setCssNameMapping
1617 | */
1618 | goog.cssNameMapping_;
1619 |
1620 |
1621 | /**
1622 | * Optional obfuscation style for CSS class names. Should be set to either
1623 | * 'BY_WHOLE' or 'BY_PART' if defined.
1624 | * @type {string|undefined}
1625 | * @private
1626 | * @see goog.setCssNameMapping
1627 | */
1628 | goog.cssNameMappingStyle_;
1629 |
1630 |
1631 |
1632 | /**
1633 | * A hook for modifying the default behavior goog.getCssName. The function
1634 | * if present, will receive the standard output of the goog.getCssName as
1635 | * its input.
1636 | *
1637 | * @type {(function(string):string)|undefined}
1638 | */
1639 | goog.global.CLOSURE_CSS_NAME_MAP_FN;
1640 |
1641 |
1642 | /**
1643 | * Handles strings that are intended to be used as CSS class names.
1644 | *
1645 | * This function works in tandem with @see goog.setCssNameMapping.
1646 | *
1647 | * Without any mapping set, the arguments are simple joined with a hyphen and
1648 | * passed through unaltered.
1649 | *
1650 | * When there is a mapping, there are two possible styles in which these
1651 | * mappings are used. In the BY_PART style, each part (i.e. in between hyphens)
1652 | * of the passed in css name is rewritten according to the map. In the BY_WHOLE
1653 | * style, the full css name is looked up in the map directly. If a rewrite is
1654 | * not specified by the map, the compiler will output a warning.
1655 | *
1656 | * When the mapping is passed to the compiler, it will replace calls to
1657 | * goog.getCssName with the strings from the mapping, e.g.
1658 | * var x = goog.getCssName('foo');
1659 | * var y = goog.getCssName(this.baseClass, 'active');
1660 | * becomes:
1661 | * var x = 'foo';
1662 | * var y = this.baseClass + '-active';
1663 | *
1664 | * If one argument is passed it will be processed, if two are passed only the
1665 | * modifier will be processed, as it is assumed the first argument was generated
1666 | * as a result of calling goog.getCssName.
1667 | *
1668 | * @param {string} className The class name.
1669 | * @param {string=} opt_modifier A modifier to be appended to the class name.
1670 | * @return {string} The class name or the concatenation of the class name and
1671 | * the modifier.
1672 | */
1673 | goog.getCssName = function(className, opt_modifier) {
1674 | // String() is used for compatibility with compiled soy where the passed
1675 | // className can be non-string objects.
1676 | if (String(className).charAt(0) == '.') {
1677 | throw new Error(
1678 | 'className passed in goog.getCssName must not start with ".".' +
1679 | ' You passed: ' + className);
1680 | }
1681 |
1682 | var getMapping = function(cssName) {
1683 | return goog.cssNameMapping_[cssName] || cssName;
1684 | };
1685 |
1686 | var renameByParts = function(cssName) {
1687 | // Remap all the parts individually.
1688 | var parts = cssName.split('-');
1689 | var mapped = [];
1690 | for (var i = 0; i < parts.length; i++) {
1691 | mapped.push(getMapping(parts[i]));
1692 | }
1693 | return mapped.join('-');
1694 | };
1695 |
1696 | var rename;
1697 | if (goog.cssNameMapping_) {
1698 | rename =
1699 | goog.cssNameMappingStyle_ == 'BY_WHOLE' ? getMapping : renameByParts;
1700 | } else {
1701 | rename = function(a) {
1702 | return a;
1703 | };
1704 | }
1705 |
1706 | var result =
1707 | opt_modifier ? className + '-' + rename(opt_modifier) : rename(className);
1708 |
1709 | // The special CLOSURE_CSS_NAME_MAP_FN allows users to specify further
1710 | // processing of the class name.
1711 | if (goog.global.CLOSURE_CSS_NAME_MAP_FN) {
1712 | return goog.global.CLOSURE_CSS_NAME_MAP_FN(result);
1713 | }
1714 |
1715 | return result;
1716 | };
1717 |
1718 |
1719 | /**
1720 | * Sets the map to check when returning a value from goog.getCssName(). Example:
1721 | *
1722 | * goog.setCssNameMapping({
1723 | * "goog": "a",
1724 | * "disabled": "b",
1725 | * });
1726 | *
1727 | * var x = goog.getCssName('goog');
1728 | * // The following evaluates to: "a a-b".
1729 | * goog.getCssName('goog') + ' ' + goog.getCssName(x, 'disabled')
1730 | *
1731 | * When declared as a map of string literals to string literals, the JSCompiler
1732 | * will replace all calls to goog.getCssName() using the supplied map if the
1733 | * --process_closure_primitives flag is set.
1734 | *
1735 | * @param {!Object} mapping A map of strings to strings where keys are possible
1736 | * arguments to goog.getCssName() and values are the corresponding values
1737 | * that should be returned.
1738 | * @param {string=} opt_style The style of css name mapping. There are two valid
1739 | * options: 'BY_PART', and 'BY_WHOLE'.
1740 | * @see goog.getCssName for a description.
1741 | */
1742 | goog.setCssNameMapping = function(mapping, opt_style) {
1743 | goog.cssNameMapping_ = mapping;
1744 | goog.cssNameMappingStyle_ = opt_style;
1745 | };
1746 |
1747 |
1748 | /**
1749 | * To use CSS renaming in compiled mode, one of the input files should have a
1750 | * call to goog.setCssNameMapping() with an object literal that the JSCompiler
1751 | * can extract and use to replace all calls to goog.getCssName(). In uncompiled
1752 | * mode, JavaScript code should be loaded before this base.js file that declares
1753 | * a global variable, CLOSURE_CSS_NAME_MAPPING, which is used below. This is
1754 | * to ensure that the mapping is loaded before any calls to goog.getCssName()
1755 | * are made in uncompiled mode.
1756 | *
1757 | * A hook for overriding the CSS name mapping.
1758 | * @type {!Object|undefined}
1759 | */
1760 | goog.global.CLOSURE_CSS_NAME_MAPPING;
1761 |
1762 |
1763 | if (!COMPILED && goog.global.CLOSURE_CSS_NAME_MAPPING) {
1764 | // This does not call goog.setCssNameMapping() because the JSCompiler
1765 | // requires that goog.setCssNameMapping() be called with an object literal.
1766 | goog.cssNameMapping_ = goog.global.CLOSURE_CSS_NAME_MAPPING;
1767 | }
1768 |
1769 |
1770 | /**
1771 | * Gets a localized message.
1772 | *
1773 | * This function is a compiler primitive. If you give the compiler a localized
1774 | * message bundle, it will replace the string at compile-time with a localized
1775 | * version, and expand goog.getMsg call to a concatenated string.
1776 | *
1777 | * Messages must be initialized in the form:
1778 | *
1779 | * var MSG_NAME = goog.getMsg('Hello {$placeholder}', {'placeholder': 'world'});
1780 | *
1781 | *
1782 | * This function produces a string which should be treated as plain text. Use
1783 | * {@link goog.html.SafeHtmlFormatter} in conjunction with goog.getMsg to
1784 | * produce SafeHtml.
1785 | *
1786 | * @param {string} str Translatable string, places holders in the form {$foo}.
1787 | * @param {Object=} opt_values Maps place holder name to value.
1788 | * @param {{html: (boolean|undefined),
1789 | * unescapeHtmlEntities: (boolean|undefined)}=} opt_options Options:
1790 | * html: Escape '<' in str to '<'. Used by Closure Templates where the
1791 | * generated code size and performance is critical which is why {@link
1792 | * goog.html.SafeHtmlFormatter} is not used. The value must be literal true
1793 | * or false.
1794 | * unescapeHtmlEntities: Unescape common html entities: >, <, ',
1795 | * " and &. Used for messages not in HTML context, such as with
1796 | * `textContent` property.
1797 | * @return {string} message with placeholders filled.
1798 | */
1799 | goog.getMsg = function(str, opt_values, opt_options) {
1800 | if (opt_options && opt_options.html) {
1801 | // Note that '&' is not replaced because the translation can contain HTML
1802 | // entities.
1803 | str = str.replace(/')
1809 | .replace(/'/g, '\'')
1810 | .replace(/"/g, '"')
1811 | .replace(/&/g, '&');
1812 | }
1813 | if (opt_values) {
1814 | str = str.replace(/\{\$([^}]+)}/g, function(match, key) {
1815 | return (opt_values != null && key in opt_values) ? opt_values[key] :
1816 | match;
1817 | });
1818 | }
1819 | return str;
1820 | };
1821 |
1822 |
1823 | /**
1824 | * Gets a localized message. If the message does not have a translation, gives a
1825 | * fallback message.
1826 | *
1827 | * This is useful when introducing a new message that has not yet been
1828 | * translated into all languages.
1829 | *
1830 | * This function is a compiler primitive. Must be used in the form:
1831 | * var x = goog.getMsgWithFallback(MSG_A, MSG_B);
1832 | * where MSG_A and MSG_B were initialized with goog.getMsg.
1833 | *
1834 | * @param {string} a The preferred message.
1835 | * @param {string} b The fallback message.
1836 | * @return {string} The best translated message.
1837 | */
1838 | goog.getMsgWithFallback = function(a, b) {
1839 | return a;
1840 | };
1841 |
1842 |
1843 | /**
1844 | * Exposes an unobfuscated global namespace path for the given object.
1845 | * Note that fields of the exported object *will* be obfuscated, unless they are
1846 | * exported in turn via this function or goog.exportProperty.
1847 | *
1848 | * Also handy for making public items that are defined in anonymous closures.
1849 | *
1850 | * ex. goog.exportSymbol('public.path.Foo', Foo);
1851 | *
1852 | * ex. goog.exportSymbol('public.path.Foo.staticFunction', Foo.staticFunction);
1853 | * public.path.Foo.staticFunction();
1854 | *
1855 | * ex. goog.exportSymbol('public.path.Foo.prototype.myMethod',
1856 | * Foo.prototype.myMethod);
1857 | * new public.path.Foo().myMethod();
1858 | *
1859 | * @param {string} publicPath Unobfuscated name to export.
1860 | * @param {*} object Object the name should point to.
1861 | * @param {?Object=} objectToExportTo The object to add the path to; default
1862 | * is goog.global.
1863 | */
1864 | goog.exportSymbol = function(publicPath, object, objectToExportTo) {
1865 | goog.exportPath_(
1866 | publicPath, object, /* overwriteImplicit= */ true, objectToExportTo);
1867 | };
1868 |
1869 |
1870 | /**
1871 | * Exports a property unobfuscated into the object's namespace.
1872 | * ex. goog.exportProperty(Foo, 'staticFunction', Foo.staticFunction);
1873 | * ex. goog.exportProperty(Foo.prototype, 'myMethod', Foo.prototype.myMethod);
1874 | * @param {Object} object Object whose static property is being exported.
1875 | * @param {string} publicName Unobfuscated name to export.
1876 | * @param {*} symbol Object the name should point to.
1877 | */
1878 | goog.exportProperty = function(object, publicName, symbol) {
1879 | object[publicName] = symbol;
1880 | };
1881 |
1882 |
1883 | /**
1884 | * Inherit the prototype methods from one constructor into another.
1885 | *
1886 | * Usage:
1887 | *
1888 | * function ParentClass(a, b) { }
1889 | * ParentClass.prototype.foo = function(a) { };
1890 | *
1891 | * function ChildClass(a, b, c) {
1892 | * ChildClass.base(this, 'constructor', a, b);
1893 | * }
1894 | * goog.inherits(ChildClass, ParentClass);
1895 | *
1896 | * var child = new ChildClass('a', 'b', 'see');
1897 | * child.foo(); // This works.
1898 | *
1899 | *
1900 | * @param {!Function} childCtor Child class.
1901 | * @param {!Function} parentCtor Parent class.
1902 | * @suppress {strictMissingProperties} superClass_ and base is not defined on
1903 | * Function.
1904 | * @deprecated Use ECMAScript class syntax instead.
1905 | */
1906 | goog.inherits = function(childCtor, parentCtor) {
1907 | /** @constructor */
1908 | function tempCtor() {}
1909 | tempCtor.prototype = parentCtor.prototype;
1910 | childCtor.superClass_ = parentCtor.prototype;
1911 | childCtor.prototype = new tempCtor();
1912 | /** @override */
1913 | childCtor.prototype.constructor = childCtor;
1914 |
1915 | /**
1916 | * Calls superclass constructor/method.
1917 | *
1918 | * This function is only available if you use goog.inherits to
1919 | * express inheritance relationships between classes.
1920 | *
1921 | * NOTE: This is a replacement for goog.base and for superClass_
1922 | * property defined in childCtor.
1923 | *
1924 | * @param {!Object} me Should always be "this".
1925 | * @param {string} methodName The method name to call. Calling
1926 | * superclass constructor can be done with the special string
1927 | * 'constructor'.
1928 | * @param {...*} var_args The arguments to pass to superclass
1929 | * method/constructor.
1930 | * @return {*} The return value of the superclass method/constructor.
1931 | */
1932 | childCtor.base = function(me, methodName, var_args) {
1933 | // Copying using loop to avoid deop due to passing arguments object to
1934 | // function. This is faster in many JS engines as of late 2014.
1935 | var args = new Array(arguments.length - 2);
1936 | for (var i = 2; i < arguments.length; i++) {
1937 | args[i - 2] = arguments[i];
1938 | }
1939 | return parentCtor.prototype[methodName].apply(me, args);
1940 | };
1941 | };
1942 |
1943 |
1944 | /**
1945 | * Allow for aliasing within scope functions. This function exists for
1946 | * uncompiled code - in compiled code the calls will be inlined and the aliases
1947 | * applied. In uncompiled code the function is simply run since the aliases as
1948 | * written are valid JavaScript.
1949 | *
1950 | *
1951 | * @param {function()} fn Function to call. This function can contain aliases
1952 | * to namespaces (e.g. "var dom = goog.dom") or classes
1953 | * (e.g. "var Timer = goog.Timer").
1954 | * @deprecated Use goog.module instead.
1955 | */
1956 | goog.scope = function(fn) {
1957 | if (goog.isInModuleLoader_()) {
1958 | throw new Error('goog.scope is not supported within a module.');
1959 | }
1960 | fn.call(goog.global);
1961 | };
1962 |
1963 |
1964 | /*
1965 | * To support uncompiled, strict mode bundles that use eval to divide source
1966 | * like so:
1967 | * eval('someSource;//# sourceUrl sourcefile.js');
1968 | * We need to export the globally defined symbols "goog" and "COMPILED".
1969 | * Exporting "goog" breaks the compiler optimizations, so we required that
1970 | * be defined externally.
1971 | * NOTE: We don't use goog.exportSymbol here because we don't want to trigger
1972 | * extern generation when that compiler option is enabled.
1973 | */
1974 | if (!COMPILED) {
1975 | goog.global['COMPILED'] = COMPILED;
1976 | }
1977 |
1978 |
1979 | //==============================================================================
1980 | // goog.defineClass implementation
1981 | //==============================================================================
1982 |
1983 |
1984 | /**
1985 | * Creates a restricted form of a Closure "class":
1986 | * - from the compiler's perspective, the instance returned from the
1987 | * constructor is sealed (no new properties may be added). This enables
1988 | * better checks.
1989 | * - the compiler will rewrite this definition to a form that is optimal
1990 | * for type checking and optimization (initially this will be a more
1991 | * traditional form).
1992 | *
1993 | * @param {Function} superClass The superclass, Object or null.
1994 | * @param {goog.defineClass.ClassDescriptor} def
1995 | * An object literal describing
1996 | * the class. It may have the following properties:
1997 | * "constructor": the constructor function
1998 | * "statics": an object literal containing methods to add to the constructor
1999 | * as "static" methods or a function that will receive the constructor
2000 | * function as its only parameter to which static properties can
2001 | * be added.
2002 | * all other properties are added to the prototype.
2003 | * @return {!Function} The class constructor.
2004 | * @deprecated Use ECMAScript class syntax instead.
2005 | */
2006 | goog.defineClass = function(superClass, def) {
2007 | // TODO(johnlenz): consider making the superClass an optional parameter.
2008 | var constructor = def.constructor;
2009 | var statics = def.statics;
2010 | // Wrap the constructor prior to setting up the prototype and static methods.
2011 | if (!constructor || constructor == Object.prototype.constructor) {
2012 | constructor = function() {
2013 | throw new Error(
2014 | 'cannot instantiate an interface (no constructor defined).');
2015 | };
2016 | }
2017 |
2018 | var cls = goog.defineClass.createSealingConstructor_(constructor, superClass);
2019 | if (superClass) {
2020 | goog.inherits(cls, superClass);
2021 | }
2022 |
2023 | // Remove all the properties that should not be copied to the prototype.
2024 | delete def.constructor;
2025 | delete def.statics;
2026 |
2027 | goog.defineClass.applyProperties_(cls.prototype, def);
2028 | if (statics != null) {
2029 | if (statics instanceof Function) {
2030 | statics(cls);
2031 | } else {
2032 | goog.defineClass.applyProperties_(cls, statics);
2033 | }
2034 | }
2035 |
2036 | return cls;
2037 | };
2038 |
2039 |
2040 | /**
2041 | * @typedef {{
2042 | * constructor: (!Function|undefined),
2043 | * statics: (Object|undefined|function(Function):void)
2044 | * }}
2045 | */
2046 | goog.defineClass.ClassDescriptor;
2047 |
2048 |
2049 | /**
2050 | * @define {boolean} Whether the instances returned by goog.defineClass should
2051 | * be sealed when possible.
2052 | *
2053 | * When sealing is disabled the constructor function will not be wrapped by
2054 | * goog.defineClass, making it incompatible with ES6 class methods.
2055 | */
2056 | goog.defineClass.SEAL_CLASS_INSTANCES =
2057 | goog.define('goog.defineClass.SEAL_CLASS_INSTANCES', goog.DEBUG);
2058 |
2059 |
2060 | /**
2061 | * If goog.defineClass.SEAL_CLASS_INSTANCES is enabled and Object.seal is
2062 | * defined, this function will wrap the constructor in a function that seals the
2063 | * results of the provided constructor function.
2064 | *
2065 | * @param {!Function} ctr The constructor whose results maybe be sealed.
2066 | * @param {Function} superClass The superclass constructor.
2067 | * @return {!Function} The replacement constructor.
2068 | * @private
2069 | */
2070 | goog.defineClass.createSealingConstructor_ = function(ctr, superClass) {
2071 | if (!goog.defineClass.SEAL_CLASS_INSTANCES) {
2072 | // Do now wrap the constructor when sealing is disabled. Angular code
2073 | // depends on this for injection to work properly.
2074 | return ctr;
2075 | }
2076 |
2077 | // NOTE: The sealing behavior has been removed
2078 |
2079 | /**
2080 | * @this {Object}
2081 | * @return {?}
2082 | */
2083 | var wrappedCtr = function() {
2084 | // Don't seal an instance of a subclass when it calls the constructor of
2085 | // its super class as there is most likely still setup to do.
2086 | var instance = ctr.apply(this, arguments) || this;
2087 | instance[goog.UID_PROPERTY_] = instance[goog.UID_PROPERTY_];
2088 |
2089 | return instance;
2090 | };
2091 |
2092 | return wrappedCtr;
2093 | };
2094 |
2095 |
2096 |
2097 | // TODO(johnlenz): share these values with the goog.object
2098 | /**
2099 | * The names of the fields that are defined on Object.prototype.
2100 | * @type {!Array}
2101 | * @private
2102 | * @const
2103 | */
2104 | goog.defineClass.OBJECT_PROTOTYPE_FIELDS_ = [
2105 | 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',
2106 | 'toLocaleString', 'toString', 'valueOf'
2107 | ];
2108 |
2109 |
2110 | // TODO(johnlenz): share this function with the goog.object
2111 | /**
2112 | * @param {!Object} target The object to add properties to.
2113 | * @param {!Object} source The object to copy properties from.
2114 | * @private
2115 | */
2116 | goog.defineClass.applyProperties_ = function(target, source) {
2117 | // TODO(johnlenz): update this to support ES5 getters/setters
2118 |
2119 | var key;
2120 | for (key in source) {
2121 | if (Object.prototype.hasOwnProperty.call(source, key)) {
2122 | target[key] = source[key];
2123 | }
2124 | }
2125 |
2126 | // For IE the for-in-loop does not contain any properties that are not
2127 | // enumerable on the prototype object (for example isPrototypeOf from
2128 | // Object.prototype) and it will also not include 'replace' on objects that
2129 | // extend String and change 'replace' (not that it is common for anyone to
2130 | // extend anything except Object).
2131 | for (var i = 0; i < goog.defineClass.OBJECT_PROTOTYPE_FIELDS_.length; i++) {
2132 | key = goog.defineClass.OBJECT_PROTOTYPE_FIELDS_[i];
2133 | if (Object.prototype.hasOwnProperty.call(source, key)) {
2134 | target[key] = source[key];
2135 | }
2136 | }
2137 | };
2138 |
2139 | /**
2140 | * Returns the parameter.
2141 | * @param {string} s
2142 | * @return {string}
2143 | * @private
2144 | */
2145 | goog.identity_ = function(s) {
2146 | return s;
2147 | };
2148 |
2149 |
2150 | /**
2151 | * Creates Trusted Types policy if Trusted Types are supported by the browser.
2152 | * The policy just blesses any string as a Trusted Type. It is not visibility
2153 | * restricted because anyone can also call trustedTypes.createPolicy directly.
2154 | * However, the allowed names should be restricted by a HTTP header and the
2155 | * reference to the created policy should be visibility restricted.
2156 | * @param {string} name
2157 | * @return {?TrustedTypePolicy}
2158 | */
2159 | goog.createTrustedTypesPolicy = function(name) {
2160 | var policy = null;
2161 | var policyFactory = goog.global.trustedTypes;
2162 | if (!policyFactory || !policyFactory.createPolicy) {
2163 | return policy;
2164 | }
2165 | // trustedTypes.createPolicy throws if called with a name that is already
2166 | // registered, even in report-only mode. Until the API changes, catch the
2167 | // error not to break the applications functionally. In such case, the code
2168 | // will fall back to using regular Safe Types.
2169 | // TODO(koto): Remove catching once createPolicy API stops throwing.
2170 | try {
2171 | policy = policyFactory.createPolicy(name, {
2172 | createHTML: goog.identity_,
2173 | createScript: goog.identity_,
2174 | createScriptURL: goog.identity_
2175 | });
2176 | } catch (e) {
2177 | goog.logToConsole_(e.message);
2178 | }
2179 | return policy;
2180 | };
2181 |
2182 | // There's a bug in the compiler where without collapse properties the
2183 | // Closure namespace defines do not guard code correctly. To help reduce code
2184 | // size also check for !COMPILED even though it redundant until this is fixed.
2185 | if (!COMPILED && goog.DEPENDENCIES_ENABLED) {
2186 |
2187 |
2188 | /**
2189 | * Tries to detect whether the current browser is Edge, based on the user
2190 | * agent. This matches only pre-Chromium Edge.
2191 | * @see https://docs.microsoft.com/en-us/microsoft-edge/web-platform/user-agent-string
2192 | * @return {boolean} True if the current browser is Edge.
2193 | * @private
2194 | */
2195 | goog.isEdge_ = function() {
2196 | var userAgent = goog.global.navigator && goog.global.navigator.userAgent ?
2197 | goog.global.navigator.userAgent :
2198 | '';
2199 | var edgeRe = /Edge\/(\d+)(\.\d)*/i;
2200 | return !!userAgent.match(edgeRe);
2201 | };
2202 |
2203 |
2204 | /**
2205 | * Tries to detect whether is in the context of an HTML document.
2206 | * @return {boolean} True if it looks like HTML document.
2207 | * @private
2208 | */
2209 | goog.inHtmlDocument_ = function() {
2210 | /** @type {!Document} */
2211 | var doc = goog.global.document;
2212 | return doc != null && 'write' in doc; // XULDocument misses write.
2213 | };
2214 |
2215 |
2216 | /**
2217 | * We'd like to check for if the document readyState is 'loading'; however
2218 | * there are bugs on IE 10 and below where the readyState being anything other
2219 | * than 'complete' is not reliable.
2220 | * @return {boolean}
2221 | * @private
2222 | */
2223 | goog.isDocumentLoading_ = function() {
2224 | // attachEvent is available on IE 6 thru 10 only, and thus can be used to
2225 | // detect those browsers.
2226 | /** @type {!HTMLDocument} */
2227 | var doc = goog.global.document;
2228 | return doc.attachEvent ? doc.readyState != 'complete' :
2229 | doc.readyState == 'loading';
2230 | };
2231 |
2232 |
2233 | /**
2234 | * Tries to detect the base path of base.js script that bootstraps Closure.
2235 | * @private
2236 | */
2237 | goog.findBasePath_ = function() {
2238 | if (goog.global.CLOSURE_BASE_PATH != undefined &&
2239 | // Anti DOM-clobbering runtime check (b/37736576).
2240 | typeof goog.global.CLOSURE_BASE_PATH === 'string') {
2241 | goog.basePath = goog.global.CLOSURE_BASE_PATH;
2242 | return;
2243 | } else if (!goog.inHtmlDocument_()) {
2244 | return;
2245 | }
2246 | /** @type {!Document} */
2247 | var doc = goog.global.document;
2248 | // If we have a currentScript available, use it exclusively.
2249 | var currentScript = doc.currentScript;
2250 | if (currentScript) {
2251 | var scripts = [currentScript];
2252 | } else {
2253 | var scripts = doc.getElementsByTagName('SCRIPT');
2254 | }
2255 | // Search backwards since the current script is in almost all cases the one
2256 | // that has base.js.
2257 | for (var i = scripts.length - 1; i >= 0; --i) {
2258 | var script = /** @type {!HTMLScriptElement} */ (scripts[i]);
2259 | var src = script.src;
2260 | var qmark = src.lastIndexOf('?');
2261 | var l = qmark == -1 ? src.length : qmark;
2262 | if (src.substr(l - 7, 7) == 'base.js') {
2263 | goog.basePath = src.substr(0, l - 7);
2264 | return;
2265 | }
2266 | }
2267 | };
2268 |
2269 | goog.findBasePath_();
2270 |
2271 | /** @struct @constructor @final */
2272 | goog.Transpiler = function() {
2273 | /** @private {?Object} */
2274 | this.requiresTranspilation_ = null;
2275 | /** @private {string} */
2276 | this.transpilationTarget_ = goog.TRANSPILE_TO_LANGUAGE;
2277 | };
2278 | /**
2279 | * Returns a newly created map from language mode string to a boolean
2280 | * indicating whether transpilation should be done for that mode as well as
2281 | * the highest level language that this environment supports.
2282 | *
2283 | * Guaranteed invariant:
2284 | * For any two modes, l1 and l2 where l2 is a newer mode than l1,
2285 | * `map[l1] == true` implies that `map[l2] == true`.
2286 | *
2287 | * Note this method is extracted and used elsewhere, so it cannot rely on
2288 | * anything external (it should easily be able to be transformed into a
2289 | * standalone, top level function).
2290 | *
2291 | * @private
2292 | * @return {{
2293 | * target: string,
2294 | * map: !Object
2295 | * }}
2296 | */
2297 | goog.Transpiler.prototype.createRequiresTranspilation_ = function() {
2298 | var transpilationTarget = 'es3';
2299 | var /** !Object */ requiresTranspilation = {'es3': false};
2300 | var transpilationRequiredForAllLaterModes = false;
2301 |
2302 | /**
2303 | * Adds an entry to requiresTranspliation for the given language mode.
2304 | *
2305 | * IMPORTANT: Calls must be made in order from oldest to newest language
2306 | * mode.
2307 | * @param {string} modeName
2308 | * @param {function(): boolean} isSupported Returns true if the JS engine
2309 | * supports the given mode.
2310 | */
2311 | function addNewerLanguageTranspilationCheck(modeName, isSupported) {
2312 | if (transpilationRequiredForAllLaterModes) {
2313 | requiresTranspilation[modeName] = true;
2314 | } else if (isSupported()) {
2315 | transpilationTarget = modeName;
2316 | requiresTranspilation[modeName] = false;
2317 | } else {
2318 | requiresTranspilation[modeName] = true;
2319 | transpilationRequiredForAllLaterModes = true;
2320 | }
2321 | }
2322 |
2323 | /**
2324 | * Does the given code evaluate without syntax errors and return a truthy
2325 | * result?
2326 | */
2327 | function /** boolean */ evalCheck(/** string */ code) {
2328 | try {
2329 | return !!eval(goog.CLOSURE_EVAL_PREFILTER_.createScript(code));
2330 | } catch (ignored) {
2331 | return false;
2332 | }
2333 | }
2334 |
2335 | // Identify ES3-only browsers by their incorrect treatment of commas.
2336 | addNewerLanguageTranspilationCheck('es5', function() {
2337 | return evalCheck('[1,].length==1');
2338 | });
2339 | addNewerLanguageTranspilationCheck('es6', function() {
2340 | // Edge has a non-deterministic (i.e., not reproducible) bug with ES6:
2341 | // https://github.com/Microsoft/ChakraCore/issues/1496.
2342 | if (goog.isEdge_()) {
2343 | // The Reflect.construct test below is flaky on Edge. It can sometimes
2344 | // pass or fail on 40 15.15063, so just exit early for Edge and treat
2345 | // it as ES5. Until we're on a more up to date version just always use
2346 | // ES5. See https://github.com/Microsoft/ChakraCore/issues/3217.
2347 | return false;
2348 | }
2349 | // Test es6: [FF50 (?), Edge 14 (?), Chrome 50]
2350 | // (a) default params (specifically shadowing locals),
2351 | // (b) destructuring, (c) block-scoped functions,
2352 | // (d) for-of (const), (e) new.target/Reflect.construct
2353 | var es6fullTest =
2354 | 'class X{constructor(){if(new.target!=String)throw 1;this.x=42}}' +
2355 | 'let q=Reflect.construct(X,[],String);if(q.x!=42||!(q instanceof ' +
2356 | 'String))throw 1;for(const a of[2,3]){if(a==2)continue;function ' +
2357 | 'f(z={a}){let a=0;return z.a}{function f(){return 0;}}return f()' +
2358 | '==3}';
2359 |
2360 | return evalCheck('(()=>{"use strict";' + es6fullTest + '})()');
2361 | });
2362 | // ** and **= are the only new features in 'es7'
2363 | addNewerLanguageTranspilationCheck('es7', function() {
2364 | return evalCheck('2**3==8');
2365 | });
2366 | // async functions are the only new features in 'es8'
2367 | addNewerLanguageTranspilationCheck('es8', function() {
2368 | return evalCheck('async()=>1,1');
2369 | });
2370 | addNewerLanguageTranspilationCheck('es9', function() {
2371 | return evalCheck('({...rest}={}),1');
2372 | });
2373 | // optional catch binding, unescaped unicode paragraph separator in strings
2374 | addNewerLanguageTranspilationCheck('es_2019', function() {
2375 | return evalCheck('let r;try{r="\u2029"}catch{};r');
2376 | });
2377 | // optional chaining, nullish coalescing
2378 | // untested/unsupported: bigint, import meta
2379 | addNewerLanguageTranspilationCheck('es_2020', function() {
2380 | return evalCheck('null?.x??1');
2381 | });
2382 | addNewerLanguageTranspilationCheck('es_next', function() {
2383 | return false; // assume it always need to transpile
2384 | });
2385 | return {target: transpilationTarget, map: requiresTranspilation};
2386 | };
2387 |
2388 |
2389 | /**
2390 | * Determines whether the given language needs to be transpiled.
2391 | * @param {string} lang
2392 | * @param {string|undefined} module
2393 | * @return {boolean}
2394 | */
2395 | goog.Transpiler.prototype.needsTranspile = function(lang, module) {
2396 | if (goog.TRANSPILE == 'always') {
2397 | return true;
2398 | } else if (goog.TRANSPILE == 'never') {
2399 | return false;
2400 | } else if (!this.requiresTranspilation_) {
2401 | var obj = this.createRequiresTranspilation_();
2402 | this.requiresTranspilation_ = obj.map;
2403 | this.transpilationTarget_ = this.transpilationTarget_ || obj.target;
2404 | }
2405 | if (lang in this.requiresTranspilation_) {
2406 | if (this.requiresTranspilation_[lang]) {
2407 | return true;
2408 | } else if (
2409 | goog.inHtmlDocument_() && module == 'es6' &&
2410 | !('noModule' in goog.global.document.createElement('script'))) {
2411 | return true;
2412 | } else {
2413 | return false;
2414 | }
2415 | } else {
2416 | throw new Error('Unknown language mode: ' + lang);
2417 | }
2418 | };
2419 |
2420 |
2421 | /**
2422 | * Lazily retrieves the transpiler and applies it to the source.
2423 | * @param {string} code JS code.
2424 | * @param {string} path Path to the code.
2425 | * @return {string} The transpiled code.
2426 | */
2427 | goog.Transpiler.prototype.transpile = function(code, path) {
2428 | // TODO(johnplaisted): We should delete goog.transpile_ and just have this
2429 | // function. But there's some compile error atm where goog.global is being
2430 | // stripped incorrectly without this.
2431 | return goog.transpile_(code, path, this.transpilationTarget_);
2432 | };
2433 |
2434 |
2435 | /** @private @final {!goog.Transpiler} */
2436 | goog.transpiler_ = new goog.Transpiler();
2437 |
2438 | /**
2439 | * Rewrites closing script tags in input to avoid ending an enclosing script
2440 | * tag.
2441 | *
2442 | * @param {string} str
2443 | * @return {string}
2444 | * @private
2445 | */
2446 | goog.protectScriptTag_ = function(str) {
2447 | return str.replace(/<\/(SCRIPT)/ig, '\\x3c/$1');
2448 | };
2449 |
2450 |
2451 | /**
2452 | * A debug loader is responsible for downloading and executing javascript
2453 | * files in an unbundled, uncompiled environment.
2454 | *
2455 | * This can be custimized via the setDependencyFactory method, or by
2456 | * CLOSURE_IMPORT_SCRIPT/CLOSURE_LOAD_FILE_SYNC.
2457 | *
2458 | * @struct @constructor @final @private
2459 | */
2460 | goog.DebugLoader_ = function() {
2461 | /** @private @const {!Object} */
2462 | this.dependencies_ = {};
2463 | /** @private @const {!Object} */
2464 | this.idToPath_ = {};
2465 | /** @private @const {!Object} */
2466 | this.written_ = {};
2467 | /** @private @const {!Array} */
2468 | this.loadingDeps_ = [];
2469 | /** @private {!Array} */
2470 | this.depsToLoad_ = [];
2471 | /** @private {boolean} */
2472 | this.paused_ = false;
2473 | /** @private {!goog.DependencyFactory} */
2474 | this.factory_ = new goog.DependencyFactory(goog.transpiler_);
2475 | /** @private @const {!Object} */
2476 | this.deferredCallbacks_ = {};
2477 | /** @private @const {!Array} */
2478 | this.deferredQueue_ = [];
2479 | };
2480 |
2481 | /**
2482 | * @param {!Array} namespaces
2483 | * @param {function(): undefined} callback Function to call once all the
2484 | * namespaces have loaded.
2485 | */
2486 | goog.DebugLoader_.prototype.bootstrap = function(namespaces, callback) {
2487 | var cb = callback;
2488 | function resolve() {
2489 | if (cb) {
2490 | goog.global.setTimeout(cb, 0);
2491 | cb = null;
2492 | }
2493 | }
2494 |
2495 | if (!namespaces.length) {
2496 | resolve();
2497 | return;
2498 | }
2499 |
2500 | var deps = [];
2501 | for (var i = 0; i < namespaces.length; i++) {
2502 | var path = this.getPathFromDeps_(namespaces[i]);
2503 | if (!path) {
2504 | throw new Error('Unregonized namespace: ' + namespaces[i]);
2505 | }
2506 | deps.push(this.dependencies_[path]);
2507 | }
2508 |
2509 | var require = goog.require;
2510 | var loaded = 0;
2511 | for (var i = 0; i < namespaces.length; i++) {
2512 | require(namespaces[i]);
2513 | deps[i].onLoad(function() {
2514 | if (++loaded == namespaces.length) {
2515 | resolve();
2516 | }
2517 | });
2518 | }
2519 | };
2520 |
2521 |
2522 | /**
2523 | * Loads the Closure Dependency file.
2524 | *
2525 | * Exposed a public function so CLOSURE_NO_DEPS can be set to false, base
2526 | * loaded, setDependencyFactory called, and then this called. i.e. allows
2527 | * custom loading of the deps file.
2528 | */
2529 | goog.DebugLoader_.prototype.loadClosureDeps = function() {
2530 | // Circumvent addDependency, which would try to transpile deps.js if
2531 | // transpile is set to always.
2532 | var relPath = 'deps.js';
2533 | this.depsToLoad_.push(this.factory_.createDependency(
2534 | goog.normalizePath_(goog.basePath + relPath), relPath, [], [], {},
2535 | false));
2536 | this.loadDeps_();
2537 | };
2538 |
2539 |
2540 | /**
2541 | * Notifies the debug loader when a dependency has been requested.
2542 | *
2543 | * @param {string} absPathOrId Path of the dependency or goog id.
2544 | * @param {boolean=} opt_force
2545 | */
2546 | goog.DebugLoader_.prototype.requested = function(absPathOrId, opt_force) {
2547 | var path = this.getPathFromDeps_(absPathOrId);
2548 | if (path &&
2549 | (opt_force || this.areDepsLoaded_(this.dependencies_[path].requires))) {
2550 | var callback = this.deferredCallbacks_[path];
2551 | if (callback) {
2552 | delete this.deferredCallbacks_[path];
2553 | callback();
2554 | }
2555 | }
2556 | };
2557 |
2558 |
2559 | /**
2560 | * Sets the dependency factory, which can be used to create custom
2561 | * goog.Dependency implementations to control how dependencies are loaded.
2562 | *
2563 | * @param {!goog.DependencyFactory} factory
2564 | */
2565 | goog.DebugLoader_.prototype.setDependencyFactory = function(factory) {
2566 | this.factory_ = factory;
2567 | };
2568 |
2569 |
2570 | /**
2571 | * Travserses the dependency graph and queues the given dependency, and all of
2572 | * its transitive dependencies, for loading and then starts loading if not
2573 | * paused.
2574 | *
2575 | * @param {string} namespace
2576 | * @private
2577 | */
2578 | goog.DebugLoader_.prototype.load_ = function(namespace) {
2579 | if (!this.getPathFromDeps_(namespace)) {
2580 | var errorMessage = 'goog.require could not find: ' + namespace;
2581 | goog.logToConsole_(errorMessage);
2582 | } else {
2583 | var loader = this;
2584 |
2585 | var deps = [];
2586 |
2587 | /** @param {string} namespace */
2588 | var visit = function(namespace) {
2589 | var path = loader.getPathFromDeps_(namespace);
2590 |
2591 | if (!path) {
2592 | throw new Error('Bad dependency path or symbol: ' + namespace);
2593 | }
2594 |
2595 | if (loader.written_[path]) {
2596 | return;
2597 | }
2598 |
2599 | loader.written_[path] = true;
2600 |
2601 | var dep = loader.dependencies_[path];
2602 | for (var i = 0; i < dep.requires.length; i++) {
2603 | if (!goog.isProvided_(dep.requires[i])) {
2604 | visit(dep.requires[i]);
2605 | }
2606 | }
2607 |
2608 | deps.push(dep);
2609 | };
2610 |
2611 | visit(namespace);
2612 |
2613 | var wasLoading = !!this.depsToLoad_.length;
2614 | this.depsToLoad_ = this.depsToLoad_.concat(deps);
2615 |
2616 | if (!this.paused_ && !wasLoading) {
2617 | this.loadDeps_();
2618 | }
2619 | }
2620 | };
2621 |
2622 |
2623 | /**
2624 | * Loads any queued dependencies until they are all loaded or paused.
2625 | *
2626 | * @private
2627 | */
2628 | goog.DebugLoader_.prototype.loadDeps_ = function() {
2629 | var loader = this;
2630 | var paused = this.paused_;
2631 |
2632 | while (this.depsToLoad_.length && !paused) {
2633 | (function() {
2634 | var loadCallDone = false;
2635 | var dep = loader.depsToLoad_.shift();
2636 |
2637 | var loaded = false;
2638 | loader.loading_(dep);
2639 |
2640 | var controller = {
2641 | pause: function() {
2642 | if (loadCallDone) {
2643 | throw new Error('Cannot call pause after the call to load.');
2644 | } else {
2645 | paused = true;
2646 | }
2647 | },
2648 | resume: function() {
2649 | if (loadCallDone) {
2650 | loader.resume_();
2651 | } else {
2652 | // Some dep called pause and then resume in the same load call.
2653 | // Just keep running this same loop.
2654 | paused = false;
2655 | }
2656 | },
2657 | loaded: function() {
2658 | if (loaded) {
2659 | throw new Error('Double call to loaded.');
2660 | }
2661 |
2662 | loaded = true;
2663 | loader.loaded_(dep);
2664 | },
2665 | pending: function() {
2666 | // Defensive copy.
2667 | var pending = [];
2668 | for (var i = 0; i < loader.loadingDeps_.length; i++) {
2669 | pending.push(loader.loadingDeps_[i]);
2670 | }
2671 | return pending;
2672 | },
2673 | /**
2674 | * @param {goog.ModuleType} type
2675 | */
2676 | setModuleState: function(type) {
2677 | goog.moduleLoaderState_ = {
2678 | type: type,
2679 | moduleName: '',
2680 | declareLegacyNamespace: false
2681 | };
2682 | },
2683 | /** @type {function(string, string, string=)} */
2684 | registerEs6ModuleExports: function(
2685 | path, exports, opt_closureNamespace) {
2686 | if (opt_closureNamespace) {
2687 | goog.loadedModules_[opt_closureNamespace] = {
2688 | exports: exports,
2689 | type: goog.ModuleType.ES6,
2690 | moduleId: opt_closureNamespace || ''
2691 | };
2692 | }
2693 | },
2694 | /** @type {function(string, ?)} */
2695 | registerGoogModuleExports: function(moduleId, exports) {
2696 | goog.loadedModules_[moduleId] = {
2697 | exports: exports,
2698 | type: goog.ModuleType.GOOG,
2699 | moduleId: moduleId
2700 | };
2701 | },
2702 | clearModuleState: function() {
2703 | goog.moduleLoaderState_ = null;
2704 | },
2705 | defer: function(callback) {
2706 | if (loadCallDone) {
2707 | throw new Error(
2708 | 'Cannot register with defer after the call to load.');
2709 | }
2710 | loader.defer_(dep, callback);
2711 | },
2712 | areDepsLoaded: function() {
2713 | return loader.areDepsLoaded_(dep.requires);
2714 | }
2715 | };
2716 |
2717 | try {
2718 | dep.load(controller);
2719 | } finally {
2720 | loadCallDone = true;
2721 | }
2722 | })();
2723 | }
2724 |
2725 | if (paused) {
2726 | this.pause_();
2727 | }
2728 | };
2729 |
2730 |
2731 | /** @private */
2732 | goog.DebugLoader_.prototype.pause_ = function() {
2733 | this.paused_ = true;
2734 | };
2735 |
2736 |
2737 | /** @private */
2738 | goog.DebugLoader_.prototype.resume_ = function() {
2739 | if (this.paused_) {
2740 | this.paused_ = false;
2741 | this.loadDeps_();
2742 | }
2743 | };
2744 |
2745 |
2746 | /**
2747 | * Marks the given dependency as loading (load has been called but it has not
2748 | * yet marked itself as finished). Useful for dependencies that want to know
2749 | * what else is loading. Example: goog.modules cannot eval if there are
2750 | * loading dependencies.
2751 | *
2752 | * @param {!goog.Dependency} dep
2753 | * @private
2754 | */
2755 | goog.DebugLoader_.prototype.loading_ = function(dep) {
2756 | this.loadingDeps_.push(dep);
2757 | };
2758 |
2759 |
2760 | /**
2761 | * Marks the given dependency as having finished loading and being available
2762 | * for require.
2763 | *
2764 | * @param {!goog.Dependency} dep
2765 | * @private
2766 | */
2767 | goog.DebugLoader_.prototype.loaded_ = function(dep) {
2768 | for (var i = 0; i < this.loadingDeps_.length; i++) {
2769 | if (this.loadingDeps_[i] == dep) {
2770 | this.loadingDeps_.splice(i, 1);
2771 | break;
2772 | }
2773 | }
2774 |
2775 | for (var i = 0; i < this.deferredQueue_.length; i++) {
2776 | if (this.deferredQueue_[i] == dep.path) {
2777 | this.deferredQueue_.splice(i, 1);
2778 | break;
2779 | }
2780 | }
2781 |
2782 | if (this.loadingDeps_.length == this.deferredQueue_.length &&
2783 | !this.depsToLoad_.length) {
2784 | // Something has asked to load these, but they may not be directly
2785 | // required again later, so load them now that we know we're done loading
2786 | // everything else. e.g. a goog module entry point.
2787 | while (this.deferredQueue_.length) {
2788 | this.requested(this.deferredQueue_.shift(), true);
2789 | }
2790 | }
2791 |
2792 | dep.loaded();
2793 | };
2794 |
2795 |
2796 | /**
2797 | * @param {!Array} pathsOrIds
2798 | * @return {boolean}
2799 | * @private
2800 | */
2801 | goog.DebugLoader_.prototype.areDepsLoaded_ = function(pathsOrIds) {
2802 | for (var i = 0; i < pathsOrIds.length; i++) {
2803 | var path = this.getPathFromDeps_(pathsOrIds[i]);
2804 | if (!path ||
2805 | (!(path in this.deferredCallbacks_) &&
2806 | !goog.isProvided_(pathsOrIds[i]))) {
2807 | return false;
2808 | }
2809 | }
2810 |
2811 | return true;
2812 | };
2813 |
2814 |
2815 | /**
2816 | * @param {string} absPathOrId
2817 | * @return {?string}
2818 | * @private
2819 | */
2820 | goog.DebugLoader_.prototype.getPathFromDeps_ = function(absPathOrId) {
2821 | if (absPathOrId in this.idToPath_) {
2822 | return this.idToPath_[absPathOrId];
2823 | } else if (absPathOrId in this.dependencies_) {
2824 | return absPathOrId;
2825 | } else {
2826 | return null;
2827 | }
2828 | };
2829 |
2830 |
2831 | /**
2832 | * @param {!goog.Dependency} dependency
2833 | * @param {!Function} callback
2834 | * @private
2835 | */
2836 | goog.DebugLoader_.prototype.defer_ = function(dependency, callback) {
2837 | this.deferredCallbacks_[dependency.path] = callback;
2838 | this.deferredQueue_.push(dependency.path);
2839 | };
2840 |
2841 |
2842 | /**
2843 | * Interface for goog.Dependency implementations to have some control over
2844 | * loading of dependencies.
2845 | *
2846 | * @record
2847 | */
2848 | goog.LoadController = function() {};
2849 |
2850 |
2851 | /**
2852 | * Tells the controller to halt loading of more dependencies.
2853 | */
2854 | goog.LoadController.prototype.pause = function() {};
2855 |
2856 |
2857 | /**
2858 | * Tells the controller to resume loading of more dependencies if paused.
2859 | */
2860 | goog.LoadController.prototype.resume = function() {};
2861 |
2862 |
2863 | /**
2864 | * Tells the controller that this dependency has finished loading.
2865 | *
2866 | * This causes this to be removed from pending() and any load callbacks to
2867 | * fire.
2868 | */
2869 | goog.LoadController.prototype.loaded = function() {};
2870 |
2871 |
2872 | /**
2873 | * List of dependencies on which load has been called but which have not
2874 | * called loaded on their controller. This includes the current dependency.
2875 | *
2876 | * @return {!Array}
2877 | */
2878 | goog.LoadController.prototype.pending = function() {};
2879 |
2880 |
2881 | /**
2882 | * Registers an object as an ES6 module's exports so that goog.modules may
2883 | * require it by path.
2884 | *
2885 | * @param {string} path Full path of the module.
2886 | * @param {?} exports
2887 | * @param {string=} opt_closureNamespace Closure namespace to associate with
2888 | * this module.
2889 | */
2890 | goog.LoadController.prototype.registerEs6ModuleExports = function(
2891 | path, exports, opt_closureNamespace) {};
2892 |
2893 |
2894 | /**
2895 | * Sets the current module state.
2896 | *
2897 | * @param {goog.ModuleType} type Type of module.
2898 | */
2899 | goog.LoadController.prototype.setModuleState = function(type) {};
2900 |
2901 |
2902 | /**
2903 | * Clears the current module state.
2904 | */
2905 | goog.LoadController.prototype.clearModuleState = function() {};
2906 |
2907 |
2908 | /**
2909 | * Registers a callback to call once the dependency is actually requested
2910 | * via goog.require + all of the immediate dependencies have been loaded or
2911 | * all other files have been loaded. Allows for lazy loading until
2912 | * require'd without pausing dependency loading, which is needed on old IE.
2913 | *
2914 | * @param {!Function} callback
2915 | */
2916 | goog.LoadController.prototype.defer = function(callback) {};
2917 |
2918 |
2919 | /**
2920 | * @return {boolean}
2921 | */
2922 | goog.LoadController.prototype.areDepsLoaded = function() {};
2923 |
2924 |
2925 | /**
2926 | * Basic super class for all dependencies Closure Library can load.
2927 | *
2928 | * This default implementation is designed to load untranspiled, non-module
2929 | * scripts in a web broswer.
2930 | *
2931 | * For transpiled non-goog.module files {@see goog.TranspiledDependency}.
2932 | * For goog.modules see {@see goog.GoogModuleDependency}.
2933 | * For untranspiled ES6 modules {@see goog.Es6ModuleDependency}.
2934 | *
2935 | * @param {string} path Absolute path of this script.
2936 | * @param {string} relativePath Path of this script relative to goog.basePath.
2937 | * @param {!Array} provides goog.provided or goog.module symbols
2938 | * in this file.
2939 | * @param {!Array} requires goog symbols or relative paths to Closure
2940 | * this depends on.
2941 | * @param {!Object} loadFlags
2942 | * @struct @constructor
2943 | */
2944 | goog.Dependency = function(
2945 | path, relativePath, provides, requires, loadFlags) {
2946 | /** @const */
2947 | this.path = path;
2948 | /** @const */
2949 | this.relativePath = relativePath;
2950 | /** @const */
2951 | this.provides = provides;
2952 | /** @const */
2953 | this.requires = requires;
2954 | /** @const */
2955 | this.loadFlags = loadFlags;
2956 | /** @private {boolean} */
2957 | this.loaded_ = false;
2958 | /** @private {!Array} */
2959 | this.loadCallbacks_ = [];
2960 | };
2961 |
2962 |
2963 | /**
2964 | * @return {string} The pathname part of this dependency's path if it is a
2965 | * URI.
2966 | */
2967 | goog.Dependency.prototype.getPathName = function() {
2968 | var pathName = this.path;
2969 | var protocolIndex = pathName.indexOf('://');
2970 | if (protocolIndex >= 0) {
2971 | pathName = pathName.substring(protocolIndex + 3);
2972 | var slashIndex = pathName.indexOf('/');
2973 | if (slashIndex >= 0) {
2974 | pathName = pathName.substring(slashIndex + 1);
2975 | }
2976 | }
2977 | return pathName;
2978 | };
2979 |
2980 |
2981 | /**
2982 | * @param {function()} callback Callback to fire as soon as this has loaded.
2983 | * @final
2984 | */
2985 | goog.Dependency.prototype.onLoad = function(callback) {
2986 | if (this.loaded_) {
2987 | callback();
2988 | } else {
2989 | this.loadCallbacks_.push(callback);
2990 | }
2991 | };
2992 |
2993 |
2994 | /**
2995 | * Marks this dependency as loaded and fires any callbacks registered with
2996 | * onLoad.
2997 | * @final
2998 | */
2999 | goog.Dependency.prototype.loaded = function() {
3000 | this.loaded_ = true;
3001 | var callbacks = this.loadCallbacks_;
3002 | this.loadCallbacks_ = [];
3003 | for (var i = 0; i < callbacks.length; i++) {
3004 | callbacks[i]();
3005 | }
3006 | };
3007 |
3008 |
3009 | /**
3010 | * Whether or not document.written / appended script tags should be deferred.
3011 | *
3012 | * @private {boolean}
3013 | */
3014 | goog.Dependency.defer_ = false;
3015 |
3016 |
3017 | /**
3018 | * Map of script ready / state change callbacks. Old IE cannot handle putting
3019 | * these properties on goog.global.
3020 | *
3021 | * @private @const {!Object}
3022 | */
3023 | goog.Dependency.callbackMap_ = {};
3024 |
3025 |
3026 | /**
3027 | * @param {function(...?):?} callback
3028 | * @return {string}
3029 | * @private
3030 | */
3031 | goog.Dependency.registerCallback_ = function(callback) {
3032 | var key = Math.random().toString(32);
3033 | goog.Dependency.callbackMap_[key] = callback;
3034 | return key;
3035 | };
3036 |
3037 |
3038 | /**
3039 | * @param {string} key
3040 | * @private
3041 | */
3042 | goog.Dependency.unregisterCallback_ = function(key) {
3043 | delete goog.Dependency.callbackMap_[key];
3044 | };
3045 |
3046 |
3047 | /**
3048 | * @param {string} key
3049 | * @param {...?} var_args
3050 | * @private
3051 | * @suppress {unusedPrivateMembers}
3052 | */
3053 | goog.Dependency.callback_ = function(key, var_args) {
3054 | if (key in goog.Dependency.callbackMap_) {
3055 | var callback = goog.Dependency.callbackMap_[key];
3056 | var args = [];
3057 | for (var i = 1; i < arguments.length; i++) {
3058 | args.push(arguments[i]);
3059 | }
3060 | callback.apply(undefined, args);
3061 | } else {
3062 | var errorMessage = 'Callback key ' + key +
3063 | ' does not exist (was base.js loaded more than once?).';
3064 | throw Error(errorMessage);
3065 | }
3066 | };
3067 |
3068 |
3069 | /**
3070 | * Starts loading this dependency. This dependency can pause loading if it
3071 | * needs to and resume it later via the controller interface.
3072 | *
3073 | * When this is loaded it should call controller.loaded(). Note that this will
3074 | * end up calling the loaded method of this dependency; there is no need to
3075 | * call it explicitly.
3076 | *
3077 | * @param {!goog.LoadController} controller
3078 | */
3079 | goog.Dependency.prototype.load = function(controller) {
3080 | if (goog.global.CLOSURE_IMPORT_SCRIPT) {
3081 | if (goog.global.CLOSURE_IMPORT_SCRIPT(this.path)) {
3082 | controller.loaded();
3083 | } else {
3084 | controller.pause();
3085 | }
3086 | return;
3087 | }
3088 |
3089 | if (!goog.inHtmlDocument_()) {
3090 | goog.logToConsole_(
3091 | 'Cannot use default debug loader outside of HTML documents.');
3092 | if (this.relativePath == 'deps.js') {
3093 | // Some old code is relying on base.js auto loading deps.js failing with
3094 | // no error before later setting CLOSURE_IMPORT_SCRIPT.
3095 | // CLOSURE_IMPORT_SCRIPT should be set *before* base.js is loaded, or
3096 | // CLOSURE_NO_DEPS set to true.
3097 | goog.logToConsole_(
3098 | 'Consider setting CLOSURE_IMPORT_SCRIPT before loading base.js, ' +
3099 | 'or setting CLOSURE_NO_DEPS to true.');
3100 | controller.loaded();
3101 | } else {
3102 | controller.pause();
3103 | }
3104 | return;
3105 | }
3106 |
3107 | /** @type {!HTMLDocument} */
3108 | var doc = goog.global.document;
3109 |
3110 | // If the user tries to require a new symbol after document load,
3111 | // something has gone terribly wrong. Doing a document.write would
3112 | // wipe out the page. This does not apply to the CSP-compliant method
3113 | // of writing script tags.
3114 | if (doc.readyState == 'complete' &&
3115 | !goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING) {
3116 | // Certain test frameworks load base.js multiple times, which tries
3117 | // to write deps.js each time. If that happens, just fail silently.
3118 | // These frameworks wipe the page between each load of base.js, so this
3119 | // is OK.
3120 | var isDeps = /\bdeps.js$/.test(this.path);
3121 | if (isDeps) {
3122 | controller.loaded();
3123 | return;
3124 | } else {
3125 | throw Error('Cannot write "' + this.path + '" after document load');
3126 | }
3127 | }
3128 |
3129 | var nonce = goog.getScriptNonce_();
3130 | if (!goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING &&
3131 | goog.isDocumentLoading_()) {
3132 | var key;
3133 | var callback = function(script) {
3134 | if (script.readyState && script.readyState != 'complete') {
3135 | script.onload = callback;
3136 | return;
3137 | }
3138 | goog.Dependency.unregisterCallback_(key);
3139 | controller.loaded();
3140 | };
3141 | key = goog.Dependency.registerCallback_(callback);
3142 |
3143 | var defer = goog.Dependency.defer_ ? ' defer' : '';
3144 | var nonceAttr = nonce ? ' nonce="' + nonce + '"' : '';
3145 | var script = '
6 |
7 |
11 |
--------------------------------------------------------------------------------
/testfiles/protopollution_test.html:
--------------------------------------------------------------------------------
1 |
6 |
7 |
11 |
--------------------------------------------------------------------------------
/testfiles/testfile:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/url.txt:
--------------------------------------------------------------------------------
1 | example.com
--------------------------------------------------------------------------------